mirror of
https://github.com/akuker/RASCSI.git
synced 2024-12-23 21:29:30 +00:00
Replaced parameter lists by map with named parameters
This commit is contained in:
parent
00a08e8d18
commit
8629dea87f
@ -108,6 +108,11 @@ const string Device::GetPaddedName() const
|
||||
return name;
|
||||
}
|
||||
|
||||
const string Device::GetParam(const string& key)
|
||||
{
|
||||
return params.find(key) != params.end() ? params[key] : "";
|
||||
}
|
||||
|
||||
void Device::SetStatusCode(int status_code)
|
||||
{
|
||||
if (status_code) {
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
@ -96,10 +96,10 @@ private:
|
||||
string revision;
|
||||
|
||||
// The parameters the device was created with
|
||||
list<string> params;
|
||||
map<string, string> params;
|
||||
|
||||
// The default parameters
|
||||
list<string> default_params;
|
||||
map<string, string> default_params;
|
||||
|
||||
// Sense Key, ASC and ASCQ
|
||||
int status_code;
|
||||
@ -110,7 +110,7 @@ public:
|
||||
virtual ~Device() {};
|
||||
|
||||
// Override for device specific initializations, to be called after all device properties have been set
|
||||
virtual bool Init(const list<string>&) { return true; };
|
||||
virtual bool Init(const map<string, string>&) { return true; };
|
||||
|
||||
virtual bool Dispatch(SCSIDEV *) = 0;
|
||||
|
||||
@ -163,13 +163,14 @@ public:
|
||||
|
||||
bool SupportsParams() const { return supports_params; }
|
||||
void SupportsParams(bool supports_paams) { this->supports_params = supports_paams; }
|
||||
const list<string> GetParams() const { return params; }
|
||||
void SetParams(const list<string>& params) { this->params = params; }
|
||||
const list<string> GetDefaultParams() const { return default_params; }
|
||||
void SetDefaultParams(const list<string>& default_params) { this->default_params = default_params; }
|
||||
const map<string, string> GetParams() const { return params; }
|
||||
const string GetParam(const string&);
|
||||
void SetParams(const map<string, string>& params) { this->params = params; }
|
||||
const map<string, string> GetDefaultParams() const { return default_params; }
|
||||
void SetDefaultParams(const map<string, string>& default_params) { this->default_params = default_params; }
|
||||
|
||||
int GetStatusCode() const { return status_code; }
|
||||
void SetStatusCode(int status_code);
|
||||
void SetStatusCode(int);
|
||||
|
||||
bool Start();
|
||||
void Stop();
|
||||
|
@ -53,8 +53,8 @@ DeviceFactory::DeviceFactory()
|
||||
default_params[SCRM] = {};
|
||||
default_params[SCMO] = {};
|
||||
default_params[SCCD] = {};
|
||||
default_params[SCBR] = { "eth0,wlan0" };
|
||||
default_params[SCDP] = { "eth0,wlan0" };
|
||||
default_params[SCBR]["interfaces"] = "eth0,wlan0";
|
||||
default_params[SCDP]["interfaces"] = "eth0,wlan0";
|
||||
}
|
||||
|
||||
DeviceFactory& DeviceFactory::instance()
|
||||
|
@ -36,7 +36,7 @@ public:
|
||||
const set<uint32_t>& GetSectorSizes(PbDeviceType type) { return sector_sizes[type]; }
|
||||
const set<uint32_t>& GetSectorSizes(const string&);
|
||||
const set<uint64_t> GetCapacities(PbDeviceType);
|
||||
const list<string>& GetDefaultParams(PbDeviceType type) { return default_params[type]; }
|
||||
const map<string, string>& GetDefaultParams(PbDeviceType type) { return default_params[type]; }
|
||||
|
||||
Device *CreateDevice(PbDeviceType type, const string& filename, const string& ext);
|
||||
|
||||
@ -46,5 +46,5 @@ private:
|
||||
|
||||
map<PbDeviceType, map<uint64_t, Geometry>> geometries;
|
||||
|
||||
map<PbDeviceType, list<string>> default_params;
|
||||
map<PbDeviceType, map<string, string>> default_params;
|
||||
};
|
||||
|
@ -85,13 +85,13 @@ bool SCSIDaynaPort::Dispatch(SCSIDEV *controller)
|
||||
return Disk::Dispatch(controller);
|
||||
}
|
||||
|
||||
bool SCSIDaynaPort::Init(const list<string>& params)
|
||||
bool SCSIDaynaPort::Init(const map<string, string>& params)
|
||||
{
|
||||
SetParams(params.empty() ? GetDefaultParams() : params);
|
||||
|
||||
#ifdef __linux__
|
||||
// TAP Driver Generation
|
||||
m_tap = new CTapDriver(GetParams().front());
|
||||
m_tap = new CTapDriver(GetParam("interfaces"));
|
||||
m_bTapEnable = m_tap->Init();
|
||||
if(!m_bTapEnable){
|
||||
LOGERROR("Unable to open the TAP interface");
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
SCSIDaynaPort();
|
||||
~SCSIDaynaPort();
|
||||
|
||||
bool Init(const list<string>&) override;
|
||||
bool Init(const map<string, string>&) override;
|
||||
void Open(const Filepath& path) override;
|
||||
|
||||
// Commands
|
||||
|
@ -63,14 +63,14 @@ SCSIBR::~SCSIBR()
|
||||
}
|
||||
}
|
||||
|
||||
bool SCSIBR::Init(const list<string>& params)
|
||||
bool SCSIBR::Init(const map<string, string>& params)
|
||||
{
|
||||
// Use default parameters if no parameters were provided
|
||||
SetParams(params.empty() ? GetDefaultParams() : params);
|
||||
|
||||
#ifdef __linux__
|
||||
// TAP Driver Generation
|
||||
tap = new CTapDriver(GetParams().front());
|
||||
tap = new CTapDriver(GetParam("interfaces"));
|
||||
m_bTapEnable = tap->Init();
|
||||
|
||||
// Generate MAC Address
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
SCSIBR();
|
||||
~SCSIBR();
|
||||
|
||||
bool Init(const list<string>&) override;
|
||||
bool Init(const map<string, string>&) override;
|
||||
bool Dispatch(SCSIDEV *) override;
|
||||
|
||||
// Commands
|
||||
|
@ -8,7 +8,6 @@
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sstream>
|
||||
#include "rascsi_interface.pb.h"
|
||||
#include "exceptions.h"
|
||||
#include "protobuf_util.h"
|
||||
@ -16,6 +15,43 @@
|
||||
using namespace std;
|
||||
using namespace rascsi_interface;
|
||||
|
||||
|
||||
const string GetParam(const PbCommand& command, const string& key)
|
||||
{
|
||||
auto map = command.params();
|
||||
return map[key];
|
||||
}
|
||||
|
||||
const string GetParam(const PbDeviceDefinition& device, const string& key)
|
||||
{
|
||||
auto map = device.params();
|
||||
return map[key];
|
||||
}
|
||||
|
||||
void AddParam(PbCommand& command, const string& key, const string& value)
|
||||
{
|
||||
if (!key.empty() && !value.empty()) {
|
||||
auto& map = *command.mutable_params();
|
||||
map[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void AddParam(PbDevice& device, const string& key, const string& value)
|
||||
{
|
||||
if (!key.empty() && !value.empty()) {
|
||||
auto& map = *device.mutable_params();
|
||||
map[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void AddParam(PbDeviceDefinition& device, const string& key, const string& value)
|
||||
{
|
||||
if (!key.empty() && !value.empty()) {
|
||||
auto& map = *device.mutable_params();
|
||||
map[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Serialize/Deserialize protobuf message: Length followed by the actual data.
|
||||
|
@ -14,6 +14,13 @@
|
||||
#include "google/protobuf/message.h"
|
||||
#include "rascsi_interface.pb.h"
|
||||
|
||||
using namespace rascsi_interface;
|
||||
|
||||
const string GetParam(const PbCommand&, const string&);
|
||||
const string GetParam(const PbDeviceDefinition&, const string&);
|
||||
void AddParam(PbCommand&, const string&, const string&);
|
||||
void AddParam(PbDevice&, const string&, const string&);
|
||||
void AddParam(PbDeviceDefinition&, const string&, const string&);
|
||||
void SerializeMessage(int, const google::protobuf::Message&);
|
||||
void DeserializeMessage(int, google::protobuf::Message&);
|
||||
int ReadNBytes(int, uint8_t *, int);
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <filesystem>
|
||||
|
||||
using namespace std;
|
||||
@ -133,7 +134,7 @@ bool InitService(int port)
|
||||
{
|
||||
int result = pthread_mutex_init(&ctrl_mutex,NULL);
|
||||
if (result != EXIT_SUCCESS){
|
||||
LOGERROR("Unable to create a mutex. Err code: %d", result);
|
||||
LOGERROR("Unable to create a mutex. Error code: %d", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -156,7 +157,7 @@ bool InitService(int port)
|
||||
// Bind
|
||||
if (bind(monsocket, (struct sockaddr *)&server,
|
||||
sizeof(struct sockaddr_in)) < 0) {
|
||||
FPRT(stderr, "Error : Already running?\n");
|
||||
FPRT(stderr, "Error: Already running?\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -489,7 +490,8 @@ PbDeviceProperties *GetDeviceProperties(const Device *device)
|
||||
|
||||
if (device->SupportsParams()) {
|
||||
for (const auto& param : device_factory.GetDefaultParams(t)) {
|
||||
properties->add_default_params(param);
|
||||
auto& map = *properties->mutable_default_params();
|
||||
map[param.first] = param.second;
|
||||
}
|
||||
}
|
||||
|
||||
@ -557,8 +559,8 @@ void GetDevice(const Device *device, PbDevice *pb_device)
|
||||
status->set_locked(device->IsLocked());
|
||||
|
||||
if (device->SupportsParams()) {
|
||||
for (const string& param : device->GetParams()) {
|
||||
pb_device->add_params(param);
|
||||
for (const auto& param : device->GetParams()) {
|
||||
AddParam(*pb_device, param.first, param.second);
|
||||
}
|
||||
}
|
||||
|
||||
@ -670,9 +672,16 @@ bool SetDefaultImageFolder(const string& f)
|
||||
return true;
|
||||
}
|
||||
|
||||
string SetReservedIds(const list<string>& ids_to_reserve)
|
||||
string SetReservedIds(const string& ids)
|
||||
{
|
||||
set<int> reserved;
|
||||
list<string> ids_to_reserve;
|
||||
stringstream ss(ids);
|
||||
string id;
|
||||
while (getline(ss, id, ',')) {
|
||||
ids_to_reserve.push_back(id);
|
||||
}
|
||||
|
||||
set<int> reserved;
|
||||
for (string id_to_reserve : ids_to_reserve) {
|
||||
int id;
|
||||
if (!GetAsInt(id_to_reserve, id)) {
|
||||
@ -693,8 +702,8 @@ string SetReservedIds(const list<string>& ids_to_reserve)
|
||||
if (!isFirst) {
|
||||
s << ", ";
|
||||
}
|
||||
s << id;
|
||||
isFirst = false;
|
||||
s << id;
|
||||
}
|
||||
|
||||
LOGINFO("Reserved IDs set to: %s", s.str().c_str());
|
||||
@ -708,22 +717,28 @@ string SetReservedIds(const list<string>& ids_to_reserve)
|
||||
|
||||
bool CreateImage(int fd, const PbCommand& command)
|
||||
{
|
||||
if (command.params().size() < 3 || command.params().Get(0).empty() || command.params().Get(1).empty()
|
||||
|| command.params().Get(2).empty()) {
|
||||
return ReturnStatus(fd, false, "Can't create image file: Missing filename, file size or permission");
|
||||
string filename = GetParam(command, "file");
|
||||
if (filename.empty()) {
|
||||
return ReturnStatus(fd, false, "Missing image filename");
|
||||
}
|
||||
|
||||
int permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||
const char *permission = command.params().Get(2).c_str();
|
||||
if (strcasecmp(permission, "true") && strcasecmp(permission, "false")) {
|
||||
return ReturnStatus(fd, false, "Invalid read-only setting '" + command.params().Get(2) + "'");
|
||||
string size = GetParam(command, "size");
|
||||
if (size.empty()) {
|
||||
return ReturnStatus(fd, false, "Missing image size");
|
||||
}
|
||||
|
||||
if (!strcasecmp(permission, "true")) {
|
||||
permissions = S_IRUSR | S_IRGRP | S_IROTH;
|
||||
string permission = GetParam(command, "read_only");
|
||||
if (permission.empty()) {
|
||||
return ReturnStatus(fd, false, "Missing read-only flag");
|
||||
}
|
||||
|
||||
string filename = command.params().Get(0);
|
||||
if (strcasecmp(permission.c_str(), "true") && strcasecmp(permission.c_str(), "false")) {
|
||||
return ReturnStatus(fd, false, "Invalid read-only flag '" + permission + "'");
|
||||
}
|
||||
|
||||
int permissions = !strcasecmp(permission.c_str(), "true") ?
|
||||
S_IRUSR | S_IRGRP | S_IROTH : S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||
|
||||
if (filename.find('/') != string::npos) {
|
||||
return ReturnStatus(fd, false, "The image filename '" + filename + "' must not contain a path");
|
||||
}
|
||||
@ -732,13 +747,13 @@ bool CreateImage(int fd, const PbCommand& command)
|
||||
|
||||
off_t len;
|
||||
try {
|
||||
len = stoul(command.params().Get(1));
|
||||
len = stoul(size);
|
||||
}
|
||||
catch(const invalid_argument& e) {
|
||||
return ReturnStatus(fd, false, "Invalid image file size " + command.params().Get(1));
|
||||
return ReturnStatus(fd, false, "Invalid image file size " + size);
|
||||
}
|
||||
catch(const out_of_range& e) {
|
||||
return ReturnStatus(fd, false, "Invalid image file size " + command.params().Get(1));
|
||||
return ReturnStatus(fd, false, "Invalid image file size " + size);
|
||||
}
|
||||
if (len < 512 || (len & 0x1ff)) {
|
||||
ostringstream error;
|
||||
@ -774,11 +789,11 @@ bool CreateImage(int fd, const PbCommand& command)
|
||||
|
||||
bool DeleteImage(int fd, const PbCommand& command)
|
||||
{
|
||||
if (command.params().size() < 1 || command.params().Get(0).empty()) {
|
||||
return ReturnStatus(fd, false, "Can't delete image file: Missing filename");
|
||||
string filename = GetParam(command, "file");
|
||||
if (filename.empty()) {
|
||||
return ReturnStatus(fd, false, "Missing image filename");
|
||||
}
|
||||
|
||||
string filename = command.params().Get(0);
|
||||
if (filename.find('/') != string::npos) {
|
||||
return ReturnStatus(fd, false, "The image filename '" + filename + "' must not contain a path");
|
||||
}
|
||||
@ -806,87 +821,95 @@ bool DeleteImage(int fd, const PbCommand& command)
|
||||
|
||||
bool RenameImage(int fd, const PbCommand& command)
|
||||
{
|
||||
if (command.params().size() < 2 || command.params().Get(0).empty() || command.params().Get(1).empty()) {
|
||||
return ReturnStatus(fd, false, "Can't rename image file: Missing filename");
|
||||
string from = GetParam(command, "from");
|
||||
if (from.empty()) {
|
||||
return ReturnStatus(fd, false, "Missing source filename");
|
||||
}
|
||||
|
||||
string src = command.params().Get(0);
|
||||
if (src.find('/') != string::npos) {
|
||||
return ReturnStatus(fd, false, "The current filename '" + src + "' must not contain a path");
|
||||
}
|
||||
string dst = command.params().Get(1);
|
||||
if (dst.find('/') != string::npos) {
|
||||
return ReturnStatus(fd, false, "The new filename '" + dst + "' must not contain a path");
|
||||
string to = GetParam(command, "to");
|
||||
if (to.empty()) {
|
||||
return ReturnStatus(fd, false, "Missing destination filename");
|
||||
}
|
||||
|
||||
src = default_image_folder + "/" + src;
|
||||
dst = default_image_folder + "/" + dst;
|
||||
if (from.find('/') != string::npos) {
|
||||
return ReturnStatus(fd, false, "The current filename '" + from + "' must not contain a path");
|
||||
}
|
||||
if (to.find('/') != string::npos) {
|
||||
return ReturnStatus(fd, false, "The new filename '" + to + "' must not contain a path");
|
||||
}
|
||||
|
||||
from = default_image_folder + "/" + from;
|
||||
to = default_image_folder + "/" + to;
|
||||
|
||||
struct stat st;
|
||||
if (!stat(dst.c_str(), &st)) {
|
||||
return ReturnStatus(fd, false, "Image file '" + dst + "' already exists");
|
||||
if (!stat(to.c_str(), &st)) {
|
||||
return ReturnStatus(fd, false, "Image file '" + to + "' already exists");
|
||||
}
|
||||
|
||||
if (rename(src.c_str(), dst.c_str())) {
|
||||
return ReturnStatus(fd, false, "Can't rename image file '" + src + "' to '" + dst + "': " + string(strerror(errno)));
|
||||
if (rename(from.c_str(), to.c_str())) {
|
||||
return ReturnStatus(fd, false, "Can't rename image file '" + from + "' to '" + to + "': " + string(strerror(errno)));
|
||||
}
|
||||
|
||||
LOGINFO("%s", string("Renamed image file '" + src + "' to '" + dst + "'").c_str());
|
||||
LOGINFO("%s", string("Renamed image file '" + from + "' to '" + to + "'").c_str());
|
||||
|
||||
return ReturnStatus(fd);
|
||||
}
|
||||
|
||||
bool CopyImage(int fd, const PbCommand& command)
|
||||
{
|
||||
if (command.params().size() < 2 || command.params().Get(0).empty() || command.params().Get(1).empty()) {
|
||||
return ReturnStatus(fd, false, "Can't copy image file: Missing filename");
|
||||
string from = GetParam(command, "from");
|
||||
if (from.empty()) {
|
||||
return ReturnStatus(fd, false, "Missing source filename");
|
||||
}
|
||||
|
||||
string src = command.params().Get(0);
|
||||
if (src.find('/') != string::npos) {
|
||||
return ReturnStatus(fd, false, "The current filename '" + src + "' must not contain a path");
|
||||
}
|
||||
string dst = command.params().Get(1);
|
||||
if (dst.find('/') != string::npos) {
|
||||
return ReturnStatus(fd, false, "The new filename '" + dst + "' must not contain a path");
|
||||
string to = GetParam(command, "to");
|
||||
if (to.empty()) {
|
||||
return ReturnStatus(fd, false, "Missing destination filename");
|
||||
}
|
||||
|
||||
src = default_image_folder + "/" + src;
|
||||
dst = default_image_folder + "/" + dst;
|
||||
if (from.find('/') != string::npos) {
|
||||
return ReturnStatus(fd, false, "The current filename '" + from + "' must not contain a path");
|
||||
}
|
||||
if (to.find('/') != string::npos) {
|
||||
return ReturnStatus(fd, false, "The new filename '" + to + "' must not contain a path");
|
||||
}
|
||||
|
||||
from = default_image_folder + "/" + from;
|
||||
to = default_image_folder + "/" + to;
|
||||
|
||||
struct stat st;
|
||||
if (!stat(dst.c_str(), &st)) {
|
||||
return ReturnStatus(fd, false, "Image file '" + dst + "' already exists");
|
||||
if (!stat(to.c_str(), &st)) {
|
||||
return ReturnStatus(fd, false, "Image file '" + to + "' already exists");
|
||||
}
|
||||
|
||||
int fd_src = open(src.c_str(), O_RDONLY, 0);
|
||||
int fd_src = open(from.c_str(), O_RDONLY, 0);
|
||||
if (fd_src == -1) {
|
||||
return ReturnStatus(fd, false, "Can't open source image file '" + src + "': " + string(strerror(errno)));
|
||||
return ReturnStatus(fd, false, "Can't open source image file '" + from + "': " + string(strerror(errno)));
|
||||
}
|
||||
|
||||
struct stat st_src;
|
||||
if (fstat(fd_src, &st_src) == -1) {
|
||||
return ReturnStatus(fd, false, "Can't read source image file '" + src + "': " + string(strerror(errno)));
|
||||
return ReturnStatus(fd, false, "Can't read source image file '" + from + "': " + string(strerror(errno)));
|
||||
}
|
||||
|
||||
int fd_dst = open(dst.c_str(), O_WRONLY | O_CREAT, st_src.st_mode);
|
||||
int fd_dst = open(to.c_str(), O_WRONLY | O_CREAT, st_src.st_mode);
|
||||
if (fd_dst == -1) {
|
||||
close (fd_dst);
|
||||
|
||||
return ReturnStatus(fd, false, "Can't open destination image file '" + dst + "': " + string(strerror(errno)));
|
||||
return ReturnStatus(fd, false, "Can't open destination image file '" + to + "': " + string(strerror(errno)));
|
||||
}
|
||||
|
||||
if (sendfile(fd_dst, fd_src, 0, st_src.st_size) == -1) {
|
||||
close(fd_dst);
|
||||
close(fd_src);
|
||||
|
||||
return ReturnStatus(fd, false, "Can't copy image file '" + src + "' to '" + dst + "': " + string(strerror(errno)));
|
||||
return ReturnStatus(fd, false, "Can't copy image file '" + from + "' to '" + to + "': " + string(strerror(errno)));
|
||||
}
|
||||
|
||||
close(fd_dst);
|
||||
close(fd_src);
|
||||
|
||||
LOGINFO("%s", string("Copied image file '" + src + "' to '" + dst + "'").c_str());
|
||||
LOGINFO("%s", string("Copied image file '" + from + "' to '" + to + "'").c_str());
|
||||
|
||||
return ReturnStatus(fd);
|
||||
}
|
||||
@ -917,7 +940,7 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry
|
||||
return ReturnStatus(fd, false, error);
|
||||
}
|
||||
|
||||
string filename = pb_device.params_size() > 0 ? pb_device.params().Get(0) : "";
|
||||
string filename = GetParam(pb_device, "file");
|
||||
string ext;
|
||||
size_t separator = filename.rfind('.');
|
||||
if (separator != string::npos) {
|
||||
@ -1027,7 +1050,7 @@ bool Attach(int fd, const PbDeviceDefinition& pb_device, Device *map[], bool dry
|
||||
return true;
|
||||
}
|
||||
|
||||
const list<string> params = { pb_device.params().begin(), pb_device.params().end() };
|
||||
std::map<string, string> params = { pb_device.params().begin(), pb_device.params().end() };
|
||||
if (!device->Init(params)) {
|
||||
error << "Initialization of " << device->GetType() << " device, ID " << id << ", unit " << unit << " failed";
|
||||
|
||||
@ -1097,7 +1120,7 @@ bool Insert(int fd, const PbDeviceDefinition& pb_device, Device *device, bool dr
|
||||
return ReturnStatus(fd, false, "Once set the device name cannot be changed anymore");
|
||||
}
|
||||
|
||||
string filename = pb_device.params_size() > 0 ? pb_device.params().Get(0): "";
|
||||
string filename = GetParam(pb_device, "file");
|
||||
if (filename.empty()) {
|
||||
return ReturnStatus(fd, false, "Missing filename for " + PbOperation_Name(INSERT));
|
||||
}
|
||||
@ -1161,13 +1184,15 @@ bool Insert(int fd, const PbDeviceDefinition& pb_device, Device *device, bool dr
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool ProcessCmd(int fd, const PbDeviceDefinition& pb_device, const PbOperation operation, const vector<string>& params, bool dryRun)
|
||||
bool ProcessCmd(int fd, const PbDeviceDefinition& pb_device, const PbCommand& command, bool dryRun)
|
||||
{
|
||||
ostringstream error;
|
||||
|
||||
const int id = pb_device.id();
|
||||
const int unit = pb_device.unit();
|
||||
const PbDeviceType type = pb_device.type();
|
||||
const PbOperation operation = command.operation();
|
||||
const map<string, string> params = { command.params().begin(), command.params().end() };
|
||||
|
||||
ostringstream s;
|
||||
s << (dryRun ? "Validating: " : "Executing: ");
|
||||
@ -1175,11 +1200,13 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pb_device, const PbOperation o
|
||||
|
||||
if (!params.empty()) {
|
||||
s << ", command params=";
|
||||
for (size_t i = 0; i < params.size(); i++) {
|
||||
if (i) {
|
||||
bool isFirst = true;
|
||||
for (const auto& param: params) {
|
||||
if (!isFirst) {
|
||||
s << ", ";
|
||||
}
|
||||
s << "'" << params[i] << "'";
|
||||
isFirst = false;
|
||||
s << param.first << "=" << param.second;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1187,11 +1214,13 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pb_device, const PbOperation o
|
||||
|
||||
if (pb_device.params_size()) {
|
||||
s << ", device params=";
|
||||
for (int i = 0; i < pb_device.params_size(); i++) {
|
||||
if (i) {
|
||||
bool isFirst = true;
|
||||
for (const auto& param: pb_device.params()) {
|
||||
if (!isFirst) {
|
||||
s << ", ";
|
||||
}
|
||||
s << "'" << pb_device.params().Get(i) << "'";
|
||||
isFirst = false;
|
||||
s << param.first << "=" << param.second;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1331,7 +1360,7 @@ bool ProcessCmd(const int fd, const PbCommand& command)
|
||||
return ReturnStatus(fd);
|
||||
|
||||
case RESERVE: {
|
||||
const list<string> ids = { command.params().begin(), command.params().end() };
|
||||
const string ids = GetParam(command, "ids");
|
||||
string invalid_id = SetReservedIds(ids);
|
||||
if (!invalid_id.empty()) {
|
||||
return ReturnStatus(fd, false, "Invalid ID " + invalid_id + " for " + PbOperation_Name(RESERVE));
|
||||
@ -1357,12 +1386,10 @@ bool ProcessCmd(const int fd, const PbCommand& command)
|
||||
break;
|
||||
}
|
||||
|
||||
const vector<string> params = { command.params().begin(), command.params().end() };
|
||||
|
||||
// Remember the list of reserved files, than run the dry run
|
||||
const auto reserved_files = FileSupport::GetReservedFiles();
|
||||
for (const auto& device : command.devices()) {
|
||||
if (!ProcessCmd(fd, device, command.operation(), params, true)) {
|
||||
if (!ProcessCmd(fd, device, command, true)) {
|
||||
// Dry run failed, restore the file list
|
||||
FileSupport::SetReservedFiles(reserved_files);
|
||||
return false;
|
||||
@ -1372,7 +1399,7 @@ bool ProcessCmd(const int fd, const PbCommand& command)
|
||||
// Restore list of reserved files, then execute the command
|
||||
FileSupport::SetReservedFiles(reserved_files);
|
||||
for (const auto& device : command.devices()) {
|
||||
if (!ProcessCmd(fd, device, command.operation(), params, false)) {
|
||||
if (!ProcessCmd(fd, device, command, false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1453,15 +1480,7 @@ bool ParseArgument(int argc, char* argv[], int& port)
|
||||
continue;
|
||||
|
||||
case 'r': {
|
||||
stringstream ss(optarg);
|
||||
string id;
|
||||
|
||||
list<string> ids;
|
||||
while (getline(ss, id, ',')) {
|
||||
ids.push_back(id);
|
||||
}
|
||||
|
||||
string invalid_id = SetReservedIds(ids);
|
||||
string invalid_id = SetReservedIds(optarg);
|
||||
if (!invalid_id.empty()) {
|
||||
cerr << "Invalid ID " << invalid_id << " for " << PbOperation_Name(RESERVE);
|
||||
return false;
|
||||
@ -1503,9 +1522,7 @@ bool ParseArgument(int argc, char* argv[], int& port)
|
||||
device->set_unit(unit);
|
||||
device->set_type(type);
|
||||
device->set_block_size(block_size);
|
||||
if (strlen(optarg)) {
|
||||
device->add_params(optarg);
|
||||
}
|
||||
AddParam(*device, "file", optarg);
|
||||
|
||||
size_t separatorPos = name.find(':');
|
||||
if (separatorPos != string::npos) {
|
||||
@ -1617,7 +1634,7 @@ static void *MonThread(void *param)
|
||||
case LOG_LEVEL: {
|
||||
LOGTRACE(string("Received " + PbOperation_Name(LOG_LEVEL) + " command").c_str());
|
||||
|
||||
string log_level = command.params_size() > 0 ? command.params().Get(0) : "";
|
||||
string log_level = GetParam(command, "level");
|
||||
bool status = SetLogLevel(log_level);
|
||||
if (!status) {
|
||||
ReturnStatus(fd, false, "Invalid log level: " + log_level);
|
||||
@ -1631,7 +1648,7 @@ static void *MonThread(void *param)
|
||||
case DEFAULT_FOLDER: {
|
||||
LOGTRACE(string("Received " + PbOperation_Name(DEFAULT_FOLDER) + " command").c_str());
|
||||
|
||||
string folder = command.params_size() > 0 ? command.params().Get(0) : "";
|
||||
string folder = GetParam(command, "folder");
|
||||
if (folder.empty()) {
|
||||
ReturnStatus(fd, false, "Can't set default image folder: Missing folder name");
|
||||
}
|
||||
|
@ -27,52 +27,82 @@ enum PbDeviceType {
|
||||
SCDP = 7;
|
||||
}
|
||||
|
||||
// rascsi remote operations, returns PbResult
|
||||
// rascsi remote operations, returning PbResult
|
||||
enum PbOperation {
|
||||
NONE = 0;
|
||||
// Gets the server information
|
||||
SERVER_INFO = 1;
|
||||
// Gets information for a list of attached devices. Returns data for all attached devices if empty.
|
||||
DEVICE_INFO = 2;
|
||||
// Set the default folder for image files. PbCommand.params contains the folder name.
|
||||
DEFAULT_FOLDER = 3;
|
||||
// Set server log level. PbCommand.params contains the log level.
|
||||
LOG_LEVEL = 4;
|
||||
|
||||
// Attach devices
|
||||
ATTACH = 5;
|
||||
ATTACH = 1;
|
||||
|
||||
// Detach devices
|
||||
DETACH = 6;
|
||||
DETACH = 2;
|
||||
|
||||
// Detach all devices, does not require a device list
|
||||
DETACH_ALL = 7;
|
||||
DETACH_ALL = 3;
|
||||
|
||||
// Start device
|
||||
START = 8;
|
||||
START = 4;
|
||||
|
||||
// Stop device, e.g. park drive
|
||||
STOP = 9;
|
||||
STOP = 5;
|
||||
|
||||
// Insert medium
|
||||
INSERT = 10;
|
||||
INSERT = 6;
|
||||
|
||||
// Eject medium
|
||||
EJECT = 11;
|
||||
EJECT = 7;
|
||||
|
||||
// Write-protect medium (not possible for read-only media)
|
||||
PROTECT = 12;
|
||||
PROTECT = 8;
|
||||
|
||||
// Make medium writable (not possible for read-only media)
|
||||
UNPROTECT = 13;
|
||||
// IDs blocked from being used, usually the IDs of the initiators (computers) in the SCSI chain.
|
||||
// PbCommand.params contains the list of IDs to reserve, or is empty in order not to reserve any ID.
|
||||
UNPROTECT = 9;
|
||||
|
||||
// Gets the server information
|
||||
SERVER_INFO = 10;
|
||||
|
||||
// Gets information for a list of attached devices. Returns data for all attached devices if empty.
|
||||
DEVICE_INFO = 11;
|
||||
|
||||
// Set the default folder for image files.
|
||||
// Parameters:
|
||||
// "folder": The default folder name.
|
||||
DEFAULT_FOLDER = 12;
|
||||
|
||||
// Set server log level.
|
||||
// Parameters:
|
||||
// "level": The new log level
|
||||
LOG_LEVEL = 13;
|
||||
|
||||
// Block IDs from being used, usually the IDs of the initiators (computers) in the SCSI chain.
|
||||
// Parameters:
|
||||
// "ids": A comma-separated list of IDs to reserve, or an empty string in order not to reserve any ID.
|
||||
RESERVE = 14;
|
||||
|
||||
// Create an image file. The image file must not yet exist.
|
||||
// PbCommand.params(0) contains the filename, PbCommand.params(1) contains the file size in bytes.
|
||||
// PbCommand.params(2) controls the file permissions. If "true" (case-insensitive) a read-only file is created.
|
||||
// The filename is relative to the default image folder and must not contain a slash.
|
||||
// The file size must be a multiple of 512.
|
||||
// Parameters:
|
||||
// "file": The filename, relative to the default image folder. It must not contain a slash.
|
||||
// "size": The file size in bytes, must be a multiple of 512
|
||||
// "read_only": "true" (case-insensitive) in order to create a read-only file, otherwise "false"
|
||||
CREATE_IMAGE = 15;
|
||||
// Delete an image file. PbCommand.params(0) contains the filename.
|
||||
// The filename is relative to the default image folder and must not contain a slash.
|
||||
|
||||
// Delete an image file.
|
||||
// Parameters:
|
||||
// "file": The filename, relative to the default image folder. It must not contain a slash.
|
||||
DELETE_IMAGE = 16;
|
||||
// Rename an image file. PbCommand.params(0) contains the current filename, PbCommand.params(1) the new name.
|
||||
// The filenames are relative to the default image folder and must not contain a slash.
|
||||
|
||||
// Rename an image file.
|
||||
// Parameters:
|
||||
// "from": The old filename, relative to the default image folder. It must not contain a slash.
|
||||
// "to": The new filename, relative to the default image folder. It must not contain a slash.
|
||||
// The new filename must not yet exist.
|
||||
RENAME_IMAGE = 17;
|
||||
// Copy an image file. PbCommand.params(0) contains the source filename, PbCommand.params(1) the destination name.
|
||||
// The filenames are relative to the default image folder and must not contain a slash.
|
||||
|
||||
// Copy an image file.
|
||||
// Parameters:
|
||||
// "from": The source filename, relative to the default image folder. It must not contain a slash.
|
||||
// "to": The destination filename, relative to the default image folder. It must not contain a slash.
|
||||
// The destination filename must not yet exist.
|
||||
COPY_IMAGE = 18;
|
||||
}
|
||||
|
||||
@ -92,8 +122,8 @@ message PbDeviceProperties {
|
||||
bool supports_file = 6;
|
||||
// Device supports parameters other than a filename
|
||||
bool supports_params = 7;
|
||||
// Ordered list of default parameters, if any (requires supports_params to be true)
|
||||
repeated string default_params = 8;
|
||||
// List of default parameters, if any (requires supports_params to be true)
|
||||
map<string, string> default_params = 8;
|
||||
// Number of supported LUNs, at least 1 (for LUN 0)
|
||||
uint32 luns = 9;
|
||||
// Unordered list of permitted block sizes in bytes, empty if the block size is not configurable
|
||||
@ -132,8 +162,8 @@ message PbDeviceDefinition {
|
||||
int32 id = 1;
|
||||
int32 unit = 2;
|
||||
PbDeviceType type = 3;
|
||||
// Optional device specific parameters, e.g. the name of an image file
|
||||
repeated string params = 4;
|
||||
// Device specific named parameters, e.g. the name of an image file
|
||||
map<string, string> params = 4;
|
||||
// The optional block size in bytes per sector, must be one of the supported block sizes for SASI/SCSI
|
||||
int32 block_size = 5;
|
||||
// The device name components
|
||||
@ -153,8 +183,8 @@ message PbDevice {
|
||||
PbDeviceStatus status = 5;
|
||||
// Image file information, if the device supports image files
|
||||
PbImageFile file = 6;
|
||||
// Ordered list of effective parameters the device was created with
|
||||
repeated string params = 7;
|
||||
// Effective parameters the device was created with
|
||||
map<string, string> params = 7;
|
||||
string vendor = 8;
|
||||
string product = 9;
|
||||
string revision = 10;
|
||||
@ -173,8 +203,8 @@ message PbCommand {
|
||||
PbOperation operation = 1;
|
||||
// The non-empty list of devices for this command
|
||||
repeated PbDeviceDefinition devices = 2;
|
||||
// The optional parameters depending on the operation, e.g. a filename, or a network interface list
|
||||
repeated string params = 3;
|
||||
// The named parameters for the operation, e.g. a filename, or a network interface list
|
||||
map<string, string> params = 3;
|
||||
}
|
||||
|
||||
// The result of a command
|
||||
|
@ -142,10 +142,8 @@ void DisplayDeviceInfo(const PbDevice& pb_device)
|
||||
cout << " ";
|
||||
}
|
||||
|
||||
if (pb_device.params_size()) {
|
||||
for (const string param : pb_device.params()) {
|
||||
cout << param << " ";
|
||||
}
|
||||
for (const auto& param : pb_device.params()) {
|
||||
cout << param.first << "=" << param.second;
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
@ -184,7 +182,7 @@ void CommandLogLevel(const string& hostname, int port, const string& log_level)
|
||||
{
|
||||
PbCommand command;
|
||||
command.set_operation(LOG_LEVEL);
|
||||
command.add_params(log_level);
|
||||
AddParam(command, "level", log_level);
|
||||
|
||||
PbResult result;
|
||||
SendCommand(hostname.c_str(), port, command, result);
|
||||
@ -194,13 +192,7 @@ void CommandReserve(const string&hostname, int port, const string& reserved_ids)
|
||||
{
|
||||
PbCommand command;
|
||||
command.set_operation(RESERVE);
|
||||
|
||||
stringstream ss(reserved_ids);
|
||||
string reserved_id;
|
||||
|
||||
while (getline(ss, reserved_id, ',')) {
|
||||
command.add_params(reserved_id);
|
||||
}
|
||||
AddParam(command, "ids", reserved_ids);
|
||||
|
||||
PbResult result;
|
||||
SendCommand(hostname.c_str(), port, command, result);
|
||||
@ -213,15 +205,15 @@ void CommandCreateImage(const string&hostname, int port, const string& image_par
|
||||
|
||||
size_t separatorPos = image_params.find(COMPONENT_SEPARATOR);
|
||||
if (separatorPos != string::npos) {
|
||||
command.add_params(image_params.substr(0, separatorPos));
|
||||
command.add_params(image_params.substr(separatorPos + 1));
|
||||
AddParam(command, "file", image_params.substr(0, separatorPos));
|
||||
AddParam(command, "size", image_params.substr(separatorPos + 1));
|
||||
}
|
||||
else {
|
||||
cerr << "Error: Invalid file description '" << image_params << "', format is NAME:SIZE" << endl;
|
||||
cerr << "Error: Invalid file descriptor '" << image_params << "', format is NAME:SIZE" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
command.add_params("false");
|
||||
AddParam(command, "read_only", "false");
|
||||
|
||||
PbResult result;
|
||||
SendCommand(hostname.c_str(), port, command, result);
|
||||
@ -231,8 +223,7 @@ void CommandDeleteImage(const string&hostname, int port, const string& filename)
|
||||
{
|
||||
PbCommand command;
|
||||
command.set_operation(DELETE_IMAGE);
|
||||
|
||||
command.add_params(filename);
|
||||
AddParam(command, "file", filename);
|
||||
|
||||
PbResult result;
|
||||
SendCommand(hostname.c_str(), port, command, result);
|
||||
@ -245,11 +236,11 @@ void CommandRenameImage(const string&hostname, int port, const string& image_par
|
||||
|
||||
size_t separatorPos = image_params.find(COMPONENT_SEPARATOR);
|
||||
if (separatorPos != string::npos) {
|
||||
command.add_params(image_params.substr(0, separatorPos));
|
||||
command.add_params(image_params.substr(separatorPos + 1));
|
||||
AddParam(command, "from", image_params.substr(0, separatorPos));
|
||||
AddParam(command, "to", image_params.substr(separatorPos + 1));
|
||||
}
|
||||
else {
|
||||
cerr << "Error: Invalid file description '" << image_params << "', format is CURRENT_NAME:NEW_NAME" << endl;
|
||||
cerr << "Error: Invalid file descriptor '" << image_params << "', format is CURRENT_NAME:NEW_NAME" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -264,11 +255,11 @@ void CommandCopyImage(const string&hostname, int port, const string& image_param
|
||||
|
||||
size_t separatorPos = image_params.find(COMPONENT_SEPARATOR);
|
||||
if (separatorPos != string::npos) {
|
||||
command.add_params(image_params.substr(0, separatorPos));
|
||||
command.add_params(image_params.substr(separatorPos + 1));
|
||||
AddParam(command, "from", image_params.substr(0, separatorPos));
|
||||
AddParam(command, "to", image_params.substr(separatorPos + 1));
|
||||
}
|
||||
else {
|
||||
cerr << "Error: Invalid file description '" << image_params << "', format is CURRENT_NAME:NEW_NAME" << endl;
|
||||
cerr << "Error: Invalid file descriptor '" << image_params << "', format is CURRENT_NAME:NEW_NAME" << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -280,7 +271,7 @@ void CommandDefaultImageFolder(const string& hostname, int port, const string& f
|
||||
{
|
||||
PbCommand command;
|
||||
command.set_operation(DEFAULT_FOLDER);
|
||||
command.add_params(folder);
|
||||
AddParam(command, "folder", folder);
|
||||
|
||||
PbResult result;
|
||||
SendCommand(hostname.c_str(), port, command, result);
|
||||
@ -387,8 +378,7 @@ void CommandServerInfo(const string& hostname, int port)
|
||||
}
|
||||
|
||||
if (properties.supports_params() && properties.default_params_size()) {
|
||||
list<string> params = { properties.default_params().begin(), properties.default_params().end() };
|
||||
params.sort([](const auto& a, const auto& b) { return a < b; });
|
||||
map<string, string> params = { properties.default_params().begin(), properties.default_params().end() };
|
||||
|
||||
cout << " Default parameters: ";
|
||||
|
||||
@ -397,7 +387,7 @@ void CommandServerInfo(const string& hostname, int port)
|
||||
if (!isFirst) {
|
||||
cout << ", ";
|
||||
}
|
||||
cout << param;
|
||||
cout << param.first << "=" << param.second;
|
||||
|
||||
isFirst = false;
|
||||
}
|
||||
@ -615,7 +605,7 @@ int main(int argc, char* argv[])
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
device->add_params(optarg);
|
||||
AddParam(*device, "folder", optarg);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
|
Loading…
Reference in New Issue
Block a user