blob: f78289473a709bf8c079901fa933e1745f217579 [file] [log] [blame]
#include <DrbdVolume.h>
#include <DrbdConnection.h>
#include <utils.h>
const std::string DrbdVolume::PROP_KEY_VOL_NR = "volume";
const std::string DrbdVolume::PROP_KEY_MINOR = "minor";
const std::string DrbdVolume::PROP_KEY_DISK = "disk";
const std::string DrbdVolume::PROP_KEY_PEER_DISK = "peer-disk";
const std::string DrbdVolume::PROP_KEY_REPLICATION = "replication";
const std::string DrbdVolume::PROP_KEY_CLIENT = "client";
const std::string DrbdVolume::PROP_KEY_PEER_CLIENT = "peer-client";
const char* DrbdVolume::DS_LABEL_DISKLESS = "Diskless";
const char* DrbdVolume::DS_LABEL_ATTACHING = "Attaching";
const char* DrbdVolume::DS_LABEL_DETACHING = "Detaching";
const char* DrbdVolume::DS_LABEL_FAILED = "Failed";
const char* DrbdVolume::DS_LABEL_NEGOTIATING = "Negotiating";
const char* DrbdVolume::DS_LABEL_INCONSISTENT = "Inconsistent";
const char* DrbdVolume::DS_LABEL_OUTDATED = "Outdated";
const char* DrbdVolume::DS_LABEL_UNKNOWN = "DUnknown";
const char* DrbdVolume::DS_LABEL_CONSISTENT = "Consistent";
const char* DrbdVolume::DS_LABEL_UP_TO_DATE = "UpToDate";
const char* DrbdVolume::RS_LABEL_OFF = "Off";
const char* DrbdVolume::RS_LABEL_ESTABLISHED = "Established";
const char* DrbdVolume::RS_LABEL_STARTING_SYNC_SOURCE = "StartingSyncS";
const char* DrbdVolume::RS_LABEL_STARTING_SYNC_TARGET = "StartingSyncT";
const char* DrbdVolume::RS_LABEL_WF_BITMAP_SOURCE = "WFBitMapS";
const char* DrbdVolume::RS_LABEL_WF_BITMAP_TARGET = "WFBitMapT";
const char* DrbdVolume::RS_LABEL_WF_SYNC_UUID = "WFSyncUUID";
const char* DrbdVolume::RS_LABEL_SYNC_SOURCE = "SyncSource";
const char* DrbdVolume::RS_LABEL_SYNC_TARGET = "SyncTarget";
const char* DrbdVolume::RS_LABEL_PAUSED_SYNC_SOURCE = "PausedSyncS";
const char* DrbdVolume::RS_LABEL_PAUSED_SYNC_TARGET = "PausedSyncT";
const char* DrbdVolume::RS_LABEL_VERIFY_SOURCE = "VerifyS";
const char* DrbdVolume::RS_LABEL_VERIFY_TARGET = "VerifyT";
const char* DrbdVolume::RS_LABEL_AHEAD = "Ahead";
const char* DrbdVolume::RS_LABEL_BEHIND = "Behind";
const char* DrbdVolume::RS_LABEL_UNKNOWN = "Unknown";
const char* DrbdVolume::CS_LABEL_ENABLED = "yes";
const char* DrbdVolume::CS_LABEL_DISABLED = "no";
const char* DrbdVolume::CS_LABEL_UNKNOWN = "unknown";
DrbdVolume::DrbdVolume(uint16_t volume_nr) :
vol_nr(volume_nr)
{
minor_nr = -1;
vol_disk_state = DrbdVolume::disk_state::UNKNOWN;
vol_repl_state = DrbdVolume::repl_state::UNKNOWN;
vol_client_state = DrbdVolume::client_state::UNKNOWN;
}
const uint16_t DrbdVolume::get_volume_nr() const
{
return vol_nr;
}
// @throws EventMessageException
void DrbdVolume::update(PropsMap& event_props)
{
std::string* prop_disk = event_props.get(&PROP_KEY_DISK);
if (prop_disk == nullptr)
{
prop_disk = event_props.get(&PROP_KEY_PEER_DISK);
}
if (prop_disk != nullptr)
{
vol_disk_state = parse_disk_state(*prop_disk);
}
std::string* prop_replication = event_props.get(&PROP_KEY_REPLICATION);
if (prop_replication != nullptr)
{
vol_repl_state = parse_repl_state(*prop_replication);
}
std::string* minor_nr_str = event_props.get(&PROP_KEY_MINOR);
if (minor_nr_str != nullptr)
{
try
{
minor_nr = DrbdVolume::parse_minor_nr(*minor_nr_str);
}
catch (NumberFormatException& nf_exc)
{
throw EventMessageException();
}
}
std::string* prop_client = event_props.get(&PROP_KEY_CLIENT);
if (prop_client == nullptr)
{
prop_client = event_props.get(&PROP_KEY_PEER_CLIENT);
}
if (prop_client != nullptr)
{
vol_client_state = parse_client_state(*prop_client);
}
}
int32_t DrbdVolume::get_minor_nr() const
{
return minor_nr;
}
// @throws EventMessageException
void DrbdVolume::set_minor_nr(int32_t value)
{
if (value >= -1 && value < 0x100000)
{
minor_nr = value;
}
else
{
throw EventMessageException();
}
}
DrbdVolume::disk_state DrbdVolume::get_disk_state() const
{
return vol_disk_state;
}
const char* DrbdVolume::get_disk_state_label() const
{
const char* label = DS_LABEL_UNKNOWN;
switch (vol_disk_state)
{
case DrbdVolume::disk_state::ATTACHING:
label = DS_LABEL_ATTACHING;
break;
case DrbdVolume::disk_state::DETACHING:
label = DS_LABEL_DETACHING;
break;
case DrbdVolume::disk_state::CONSISTENT:
label = DS_LABEL_CONSISTENT;
break;
case DrbdVolume::disk_state::DISKLESS:
label = DS_LABEL_DISKLESS;
break;
case DrbdVolume::disk_state::FAILED:
label = DS_LABEL_FAILED;
break;
case DrbdVolume::disk_state::INCONSISTENT:
label = DS_LABEL_INCONSISTENT;
break;
case DrbdVolume::disk_state::NEGOTIATING:
label = DS_LABEL_NEGOTIATING;
break;
case DrbdVolume::disk_state::OUTDATED:
label = DS_LABEL_OUTDATED;
break;
case DrbdVolume::disk_state::UP_TO_DATE:
label = DS_LABEL_UP_TO_DATE;
break;
case DrbdVolume::disk_state::UNKNOWN:
// fall-through
default:
break;
}
return label;
}
DrbdVolume::repl_state DrbdVolume::get_replication_state() const
{
return vol_repl_state;
}
const char* DrbdVolume::get_replication_state_label() const
{
const char* label = RS_LABEL_UNKNOWN;
switch (vol_repl_state)
{
case DrbdVolume::repl_state::AHEAD:
label = RS_LABEL_AHEAD;
break;
case DrbdVolume::repl_state::BEHIND:
label = RS_LABEL_BEHIND;
break;
case DrbdVolume::repl_state::ESTABLISHED:
label = RS_LABEL_ESTABLISHED;
break;
case DrbdVolume::repl_state::OFF:
label = RS_LABEL_OFF;
break;
case DrbdVolume::repl_state::PAUSED_SYNC_SOURCE:
label = RS_LABEL_PAUSED_SYNC_SOURCE;
break;
case DrbdVolume::repl_state::PAUSED_SYNC_TARGET:
label = RS_LABEL_PAUSED_SYNC_TARGET;
break;
case DrbdVolume::repl_state::STARTING_SYNC_SOURCE:
label = RS_LABEL_STARTING_SYNC_SOURCE;
break;
case DrbdVolume::repl_state::STARTING_SYNC_TARGET:
label = RS_LABEL_STARTING_SYNC_TARGET;
break;
case DrbdVolume::repl_state::SYNC_SOURCE:
label = RS_LABEL_SYNC_SOURCE;
break;
case DrbdVolume::repl_state::SYNC_TARGET:
label = RS_LABEL_SYNC_TARGET;
break;
case DrbdVolume::repl_state::VERIFY_SOURCE:
label = RS_LABEL_VERIFY_SOURCE;
break;
case DrbdVolume::repl_state::VERIFY_TARGET:
label = RS_LABEL_VERIFY_TARGET;
break;
case DrbdVolume::repl_state::WF_BITMAP_SOURCE:
label = RS_LABEL_WF_BITMAP_SOURCE;
break;
case DrbdVolume::repl_state::WF_BITMAP_TARGET:
label = RS_LABEL_WF_BITMAP_TARGET;
break;
case DrbdVolume::repl_state::WF_SYNC_UUID:
label = RS_LABEL_WF_SYNC_UUID;
break;
case DrbdVolume::repl_state::UNKNOWN:
// fall-through
default:
break;
}
return label;
}
void DrbdVolume::set_connection(DrbdConnection* conn)
{
connection = conn;
}
bool DrbdVolume::has_disk_alert()
{
return disk_alert;
}
bool DrbdVolume::has_replication_warning()
{
return repl_warn || repl_alert;
}
bool DrbdVolume::has_replication_alert()
{
return repl_alert;
}
void DrbdVolume::clear_state_flags()
{
disk_alert = false;
repl_warn = false;
repl_alert = false;
StateFlags::clear_state_flags();
}
StateFlags::state DrbdVolume::update_state_flags()
{
// Reset the state to normal
StateFlags::clear_state_flags();
disk_alert = false;
repl_warn = false;
repl_alert = false;
// Check the volume's disk state
switch (vol_disk_state)
{
case DrbdVolume::disk_state::UP_TO_DATE:
// UpToDate disk, no alert
break;
case DrbdVolume::disk_state::DISKLESS:
// If the volume is not configured as a diskless DRBD client,
// then trigger a disk alert
if (vol_client_state != DrbdVolume::client_state::ENABLED)
{
disk_alert = true;
set_alert();
}
break;
case DrbdVolume::disk_state::UNKNOWN:
if (connection == nullptr)
{
// Volume is local, always issue an alert for
// an unknown disk state
disk_alert = true;
set_alert();
}
else
{
// Volume is a peer volume, if the connection
// to the peer is faulty, do not issue an alert for
// an unknown disk state
if (!connection->has_warn_state())
{
disk_alert = true;
set_alert();
}
}
break;
case DrbdVolume::disk_state::ATTACHING:
// fall-through
case DrbdVolume::disk_state::CONSISTENT:
// fall-through
case DrbdVolume::disk_state::DETACHING:
// fall-through
case DrbdVolume::disk_state::FAILED:
// fall-through
case DrbdVolume::disk_state::INCONSISTENT:
// fall-through
case DrbdVolume::disk_state::NEGOTIATING:
// fall-through
case DrbdVolume::disk_state::OUTDATED:
// fall-through
default:
disk_alert = true;
set_alert();
break;
}
// Check the volume's replication state
switch (vol_repl_state)
{
case DrbdVolume::repl_state::ESTABLISHED:
// no warning, no alert
break;
case DrbdVolume::repl_state::PAUSED_SYNC_SOURCE:
// fall-through
case DrbdVolume::repl_state::PAUSED_SYNC_TARGET:
// fall-through
case DrbdVolume::repl_state::STARTING_SYNC_SOURCE:
// fall-through
case DrbdVolume::repl_state::STARTING_SYNC_TARGET:
// fall-through
case DrbdVolume::repl_state::SYNC_SOURCE:
// fall-through
case DrbdVolume::repl_state::SYNC_TARGET:
// fall-through
case DrbdVolume::repl_state::VERIFY_SOURCE:
// fall-through
case DrbdVolume::repl_state::VERIFY_TARGET:
// fall-through
case DrbdVolume::repl_state::WF_BITMAP_SOURCE:
// fall-through
case DrbdVolume::repl_state::WF_BITMAP_TARGET:
// fall-through
case DrbdVolume::repl_state::WF_SYNC_UUID:
repl_warn = true;
set_warn();
break;
case DrbdVolume::repl_state::UNKNOWN:
// fall-through
case DrbdVolume::repl_state::OFF:
if (connection != nullptr)
{
// Volume is a peer volume, if the connection
// to the peer is faulty, do not issue alerts for
// inoperative replication
if (!connection->has_warn_state())
{
repl_alert = true;
set_alert();
}
}
// No alert is issued for local (non-peer) volumes,
// because those always have 'Unknown' replication state
break;
case DrbdVolume::repl_state::AHEAD:
// fall-through
case DrbdVolume::repl_state::BEHIND:
// fall-through
default:
repl_alert = true;
set_alert();
break;
}
return obj_state;
}
// @throws EventMessageException
DrbdVolume::disk_state DrbdVolume::parse_disk_state(std::string& state_name)
{
DrbdVolume::disk_state state = DrbdVolume::disk_state::UNKNOWN;
if (state_name == DS_LABEL_DISKLESS)
{
state = DrbdVolume::disk_state::DISKLESS;
}
else
if (state_name == DS_LABEL_ATTACHING)
{
state = DrbdVolume::disk_state::ATTACHING;
}
else
if (state_name == DS_LABEL_DETACHING)
{
state = DrbdVolume::disk_state::DETACHING;
}
else
if (state_name == DS_LABEL_FAILED)
{
state = DrbdVolume::disk_state::FAILED;
}
else
if (state_name == DS_LABEL_NEGOTIATING)
{
state = DrbdVolume::disk_state::NEGOTIATING;
}
else
if (state_name == DS_LABEL_INCONSISTENT)
{
state = DrbdVolume::disk_state::INCONSISTENT;
}
else
if (state_name == DS_LABEL_OUTDATED)
{
state = DrbdVolume::disk_state::OUTDATED;
}
else
if (state_name == DS_LABEL_CONSISTENT)
{
state = DrbdVolume::disk_state::CONSISTENT;
}
else
if (state_name == DS_LABEL_UP_TO_DATE)
{
state = DrbdVolume::disk_state::UP_TO_DATE;
}
else
if (state_name != DS_LABEL_UNKNOWN)
{
throw EventMessageException();
}
return state;
}
// @throws EventMessageException
DrbdVolume::repl_state DrbdVolume::parse_repl_state(std::string& state_name)
{
DrbdVolume::repl_state state = DrbdVolume::repl_state::UNKNOWN;
if (state_name == RS_LABEL_AHEAD)
{
state = DrbdVolume::repl_state::AHEAD;
}
else
if (state_name == RS_LABEL_BEHIND)
{
state = DrbdVolume::repl_state::BEHIND;
}
else
if (state_name == RS_LABEL_ESTABLISHED)
{
state = DrbdVolume::repl_state::ESTABLISHED;
}
else
if (state_name == RS_LABEL_OFF)
{
state = DrbdVolume::repl_state::OFF;
}
else
if (state_name == RS_LABEL_PAUSED_SYNC_SOURCE)
{
state = DrbdVolume::repl_state::PAUSED_SYNC_SOURCE;
}
else
if (state_name == RS_LABEL_PAUSED_SYNC_TARGET)
{
state = DrbdVolume::repl_state::PAUSED_SYNC_TARGET;
}
else
if (state_name == RS_LABEL_STARTING_SYNC_SOURCE)
{
state = DrbdVolume::repl_state::STARTING_SYNC_SOURCE;
}
else
if (state_name == RS_LABEL_STARTING_SYNC_TARGET)
{
state = DrbdVolume::repl_state::STARTING_SYNC_TARGET;
}
else
if (state_name == RS_LABEL_SYNC_SOURCE)
{
state = DrbdVolume::repl_state::SYNC_SOURCE;
}
else
if (state_name == RS_LABEL_SYNC_TARGET)
{
state = DrbdVolume::repl_state::SYNC_TARGET;
}
else
if (state_name == RS_LABEL_VERIFY_SOURCE)
{
state = DrbdVolume::repl_state::VERIFY_SOURCE;
}
else
if (state_name == RS_LABEL_VERIFY_TARGET)
{
state = DrbdVolume::repl_state::VERIFY_TARGET;
}
else
if (state_name == RS_LABEL_WF_BITMAP_SOURCE)
{
state = DrbdVolume::repl_state::WF_BITMAP_SOURCE;
}
else
if (state_name == RS_LABEL_WF_BITMAP_TARGET)
{
state = DrbdVolume::repl_state::WF_BITMAP_TARGET;
}
else
if (state_name == RS_LABEL_WF_SYNC_UUID)
{
state = DrbdVolume::repl_state::WF_SYNC_UUID;
}
else
if (state_name != RS_LABEL_UNKNOWN)
{
throw EventMessageException();
}
return state;
}
// @throws EventMessageException
DrbdVolume::client_state DrbdVolume::parse_client_state(std::string& value_str)
{
DrbdVolume::client_state state = DrbdVolume::client_state::UNKNOWN;
if (value_str == CS_LABEL_DISABLED)
{
state = DrbdVolume::client_state::DISABLED;
}
else
if (value_str == CS_LABEL_ENABLED)
{
state = DrbdVolume::client_state::ENABLED;
}
else
if (value_str != CS_LABEL_UNKNOWN)
{
throw EventMessageException();
}
return state;
}
// @throws NumberFormatException
uint16_t DrbdVolume::parse_volume_nr(std::string& value_str)
{
uint16_t value {0};
value = NumberParser::parse_uint16(value_str);
return value;
}
// @throws NumberFormatException
int32_t DrbdVolume::parse_minor_nr(std::string& value_str)
{
int32_t value {-1};
value = NumberParser::parse_int32(value_str);
return value;
}
// Creates (allocates and initializes) a new DrbdVolume object from a map of properties
//
// @param event_props Reference to the map of properties from a 'drbdsetup events2' line
// @return Pointer to a newly created DrbdVolume object
// @throws std::bad_alloc, EventMessageException
DrbdVolume* DrbdVolume::new_from_props(PropsMap& event_props)
{
DrbdVolume* vol {nullptr};
std::string* number_str = event_props.get(&PROP_KEY_VOL_NR);
if (number_str != nullptr)
{
try
{
uint16_t vol_nr = NumberParser::parse_uint16(*number_str);
vol = new DrbdVolume(vol_nr);
}
catch (NumberFormatException& nf_exc)
{
// no-op
}
}
if (vol == nullptr)
{
throw EventMessageException();
}
return vol;
}