drbd-reactor.umh(5)
| DRBD-REACTOR.UMH(5) | File Formats Manual | DRBD-REACTOR.UMH(5) |
NAME
drbd-reactor.umh —
drbd-reactor user mode helper plugin
DESCRIPTION
drbd-reactor.umh is the user mode helper
plugin for drbd-reactor(1).
The user mode helper is a plugin that allows users to specify filters matched on DRBD state changes. If a filter rule matches, a user defined script gets executed. Information is passed to scripts via environment variables. For every event all rules are evaluated, so if multiple rules match, multiple actions are executed (concurrently).
There are 4 different types a rule can be defined for:
It is important to note that fields not specified do not restrict the filter. Think of them as “don't care”. Make sure to read and understand the implied CAVEATS section.
COMMON FIELDS
Every rule type (e.g., resource, device,...) has a set of common fields
| Common fields | Description | Type | Mandatory |
| name | Name of the rule written to logs | String | no |
| command | Command/script to execute via sh -c | String | yes |
| env | User defined env variables | Map | no |
Every type also has a common set of filters that can be used for matching.
| Common filters | Description | Type |
| resource-name | Name of the DRBD resource | String |
| event-type | Type of the event | EventType |
STATE CHANGES
Every field shown in this section marked as state change can be set on the old and/or new section of a rule. This can be used to filter state changes (e.g., from Secondary to Primary ).
RESOURCE RULES
| Fields | Description | Type | State change |
| role | Role of the resource | Role | yes |
| may-promote | If the resource may be promoted | Boolean | yes |
A match on such a rule calls the specified command and sets the following environment variables:
DRBD_RES_NAME- Name of the DRBD resource
DRBD_{OLD,NEW}_ROLE- Role of the resource
DRBD_{OLD,NEW}_MAY_PROMOTE- Resource may be promoted to Primary
DEVICE RULES
| Fields | Description | Type | State change |
| volume | Volume number | Integer | no |
| disk-state | Disk state of the device | DiskState | yes |
| client | Device is a DRBD client | Boolean | yes |
| quorum | Device has DRBD quorum | Boolean | yes |
| open | Device is opened | Boolean | yes |
A match on such a rule calls the specified command and sets the following environment variables:
DRBD_RES_NAME- Name of the DRBD resource
DRBD_MINOR- Minor number of the device
DRBD_MINOR_$volume- Minor number of the device by volume
DRBD_VOLUME- volume (number) of the device
DRBD_BACKING_DEV- Block device path to backing device or “none”
DRBD_BACKING_DEV_$volume- Block device path to backing device or “none” by volume
DRBD_{OLD,NEW}_DISK_STATE- DiskState of the device
DRBD_{OLD,NEW}_CLIENT- Device was/is a DRBD client
DRBD_{OLD,NEW}_QUORUM- Device had/has DRBD qourum
DRBD_{OLD,NEW}_OPEN- Device was/is opened
PEER DEVICE RULES
| Fields | Description | Type | State change |
| volume | Volume number | Integer | no |
| peer-node-id | Node ID of the Peer | Integer | no |
| peer-disk-state | Disk state of the peer-device | DiskState | yes |
| peer-client | Peer-device is a DRBD client | Boolean | yes |
| resync-suspended | DRBD resync is suspended | Boolean | yes |
| replication-state | Replication state | ReplicationState | yes |
A match on such a rule calls the specified command and sets the following environment variables:
DRBD_{OLD,NEW}_DISK_STATE- DiskState of the device
DRBD_RES_NAME- Name of the DRBD resource
DRBD_MINOR- Minor number of the device
DRBD_MINOR_$volume- Minor number of the device by volume
DRBD_VOLUME- volume (number) of the device
DRBD_BACKING_DEV- Block device path to backing device or “none”
DRBD_BACKING_DEV_$volume- Block device path to backing device or “none” by volume
DRBD_PEER_NODE_ID- Node ID of the peer
DRBD_{OLD,NEW}_PEER_DISK_STATE- DiskState of the peer-device
DRBD_{OLD,NEW}_PEER_CLIENT- Peer-device was/is a DRBD client
DRBD_{OLD,NEW}_PEER_RESYNC_SUSPENDED- Resync was/is suspended
DRBD_{OLD,NEW}_PEER_REPLICATION_STATE- ReplicationState
A note on DRBD_BACKING_DEV* : DRBD does not know the backing device path of its peer, so the device set in these variables is the local backing device path! Usually the backing device names on all peers are the same for diskful nodes, but it is not strictly required. This was not invented by drbd-reactor(1), this is how these variables always have been set when DRBD kernel called user mode helpers from kernel space. So this might be unexpected, but that is what it always was.
CONNECTION RULES
| Fields | Description | Type | State change |
| peer-node-id | Node ID of the Peer | Integer | no |
| conn-name | Name of the connection | String | yes |
| connection-state | Connection state | ConnectionState | yes |
| peer-role | Peer role | Role | yes |
| congested | Connection is congested | Boolean | yes |
A match on such a rule calls the specified command and sets the following environment variables:
DRBD_RES_NAME- Name of the DRBD resource
DRBD_PEER_NODE_ID- Node ID of the peer
DRBD_CSTATE- Connection state
DRBD_{OLD,NEW}_CONN_NAME- Conneciton name
DRBD_{OLD,NEW}_CONN_STATE- Connection state
DRBD_{OLD,NEW}_PEER_ROLE- Peer role
DRBD_{OLD,NEW}_CONGESTED- Connection was/is congested
ENVIRONMENT
Before a command is executed its environment gets deleted. Then the common environment variables in this section are set, followed by the filter type specific environment variables, and the user defined ones.
HOME- “/”
TERM- “Linux”
PATH- “/sbin:/usr/sbin:/bin:/usr/bin”
OPERATORS
Currently filters that are set are compared for equality with the value received in a state update. One handy operator is "not equal", meaning everthing except the given value. We have to play within the boundaries of toml, and we did not want to sacrifice type safety we get for free from the parser by inventing our own “filter language”.
The default comparison operator is Equals
old.role = Primary # compares for
equalityIf another operator should be used, one has to specify the value and the operator
old.role = { operator = "NotEquals", value = "Primary" }
# which is toml equivalent to these two lines:
old.role.operator = "NotEquals"
old.role.value = "Primary"
It is not possible to mix and match these two notations:
old.role.operator = "NotEquals" old.role = "Primary" # fails. it requires a .value in this case
The allowed operators are:
- Equals (the default)
- NotEquals
TYPES
EVENT TYPES
- Exists
- Create
- Destroy
- Change
RESOURCE ROLES
- Unknown
- Primary
- Secondary
DISK STATES
- Diskless
- Attaching
- Detaching
- Failed
- Negotiating
- Inconsistent
- Outdated
- DUnknown
- Consistent
- UpToDate
REPLICATION STATES
- Off
- Established
- StartingSyncS
- StartingSyncT
- WFBitMapS
- WFBitMapT
- WFSyncUUID
- SyncSource
- SyncTarget
- VerifyS
- VerifyT
- PausedSyncS
- PausedSyncT
- Ahead
- Behind
CONNECTION STATES
- StandAlone
- Disconnecting
- Unconnected
- Timeout
- BrokenPipe
- NetworkFailure
- ProtocolError
- TearDown
- Connecting
- Connected
EXAMPLES
Configure a user mode helper filter of type resource.
[[umh]]
[[umh.resource]]
command = "slack.sh $DRBD_RES_NAME on $(uname -n) from $DRBD_OLD_ROLE to $DRBD_NEW_ROLE"
event-type = "Change"
old.role = { operator = "NotEquals", value = "Primary" }
new.role = "Primary"
AUTHORS
The drbd-reactor(1)
program was written by the following authors:
Roland Kammerer
<rck@linbit.com>
Moritz Wanzenböck
<moritz.wanzenboeck@linbit.com>
CAVEATS
As it was mentioned before, fields that are not set are not taken into consideration when matching the filter. Let's look at how one might write a filter:
[[umh.resource]] command = "/usr/local/bin/primary.sh" resource-name = "foo" new.role = "Primary"
What this means is that this filter does *not* care about the state of the old role. So if the resource changes for whatever reason, not related to it's role, an update is sent and the current state is matched against the rule. In this case it would trigger as the the role "changes" from the old state “don't care” (i.e., already Primary) to current/new state Primary.
Most rules are written to match specific state changes anyways, so a natural fit would be:
[[umh.resource]] command = "/usr/local/bin/primary.sh" resource-name = "foo" old.role = "Secondary" new.role = "Primary"
Another possibility for more complex fields than a resource's role, capturing everthing besides a given target value look like this. See section OPERATORS for details:
[[umh.resource]]
command = "/usr/local/bin/primary.sh"
resource-name = "foo"
old.role = { operator = "NotEquals", value = "Primary" }
new.role = "Primary"
| July 22, 2026 | Linux 6.12.85-6.12-alt1 |
