feat(pacemaker): make VIPs a list of sets and impl dependsOn
All checks were successful
Discord / discord commits (push) Has been skipped
All checks were successful
Discord / discord commits (push) Has been skipped
This commit is contained in:
parent
33f3d60f1c
commit
711d088988
2 changed files with 102 additions and 60 deletions
|
@ -13,7 +13,13 @@
|
||||||
resources = {
|
resources = {
|
||||||
"caddy" = {
|
"caddy" = {
|
||||||
enable = true;
|
enable = true;
|
||||||
virtualIp = "10.0.0.130";
|
virtualIps = [
|
||||||
|
{
|
||||||
|
id = "main";
|
||||||
|
interface = "eno1";
|
||||||
|
ip = "10.0.0.130";
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
concatMapStringsSep
|
concatMapStringsSep
|
||||||
elemAt
|
elemAt
|
||||||
filterAttrs
|
filterAttrs
|
||||||
|
isAttrs
|
||||||
mkIf
|
mkIf
|
||||||
mkOption
|
mkOption
|
||||||
types
|
types
|
||||||
|
@ -25,11 +26,6 @@ in {
|
||||||
imports = ["${nixpkgs-pacemaker}/nixos/modules/${pacemakerPath}"];
|
imports = ["${nixpkgs-pacemaker}/nixos/modules/${pacemakerPath}"];
|
||||||
|
|
||||||
options.services.pacemaker = {
|
options.services.pacemaker = {
|
||||||
networkInterface = mkOption {
|
|
||||||
default = "eno1";
|
|
||||||
type = types.str;
|
|
||||||
};
|
|
||||||
|
|
||||||
resources = mkOption {
|
resources = mkOption {
|
||||||
default = {};
|
default = {};
|
||||||
type = with types;
|
type = with types;
|
||||||
|
@ -45,14 +41,36 @@ in {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtualIp = mkOption {
|
# TODO: add assertion to not have same id
|
||||||
default = null;
|
virtualIps = mkOption {
|
||||||
type = types.nullOr types.str;
|
default = [];
|
||||||
|
type = with types;
|
||||||
|
listOf (submodule {
|
||||||
|
options = {
|
||||||
|
id = mkOption {
|
||||||
|
type = types.str;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface = mkOption {
|
||||||
|
default = "eno1";
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
|
||||||
|
ip = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
|
||||||
|
cidr = mkOption {
|
||||||
|
default = 24;
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
# TODO: add assertion, needs to be an existing systemdName
|
||||||
dependsOn = mkOption {
|
dependsOn = mkOption {
|
||||||
default = [];
|
default = [];
|
||||||
# TODO: implement dependsOn
|
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -64,46 +82,48 @@ in {
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
systemd.services = let
|
systemd.services = let
|
||||||
mkVirtIp = res: ''
|
mkVirtIps = res:
|
||||||
<primitive class="ocf" id="${res.systemdName}vip" provider="heartbeat" type="IPaddr2">
|
concatMapStringsSep "\n" (vip: ''
|
||||||
<instance_attributes id="${res.systemdName}vip-attrs">
|
<primitive class="ocf" id="${res.systemdName}-${vip.id}-vip" provider="heartbeat" type="IPaddr2">
|
||||||
|
<instance_attributes id="${res.systemdName}-${vip.id}-vip-attrs">
|
||||||
<nvpair
|
<nvpair
|
||||||
id="${res.systemdName}vip-attrs-cidr_netmask"
|
id="${res.systemdName}-${vip.id}-vip-attrs-cidr_netmask"
|
||||||
name="cidr_netmask"
|
name="cidr_netmask"
|
||||||
value="24"
|
value="${toString vip.cidr}"
|
||||||
/>
|
/>
|
||||||
<nvpair
|
<nvpair
|
||||||
id="${res.systemdName}vip-attrs-ip"
|
id="${res.systemdName}-${vip.id}-vip-attrs-ip"
|
||||||
name="ip"
|
name="ip"
|
||||||
value="${res.virtualIp}"
|
value="${vip.ip}"
|
||||||
/>
|
/>
|
||||||
<nvpair
|
<nvpair
|
||||||
id="${res.systemdName}vip-attrs-nic"
|
id="${res.systemdName}-${vip.id}-vip-attrs-nic"
|
||||||
name="nic"
|
name="nic"
|
||||||
value="${cfg.networkInterface}"
|
value="${vip.interface}"
|
||||||
/>
|
/>
|
||||||
</instance_attributes>
|
</instance_attributes>
|
||||||
<operations>
|
<operations>
|
||||||
<op
|
<op
|
||||||
id="${res.systemdName}vip-monitor-interval-30s"
|
id="${res.systemdName}-${vip.id}-vip-monitor-interval-30s"
|
||||||
interval="30s"
|
interval="30s"
|
||||||
name="monitor"
|
name="monitor"
|
||||||
/>
|
/>
|
||||||
<op
|
<op
|
||||||
id="${res.systemdName}vip-start-interval-0s"
|
id="${res.systemdName}-${vip.id}-vip-start-interval-0s"
|
||||||
interval="0s"
|
interval="0s"
|
||||||
name="start"
|
name="start"
|
||||||
timeout="20s"
|
timeout="20s"
|
||||||
/>
|
/>
|
||||||
<op
|
<op
|
||||||
id="${res.systemdName}vip-stop-interval-0s"
|
id="${res.systemdName}-${vip.id}-vip-stop-interval-0s"
|
||||||
interval="0s"
|
interval="0s"
|
||||||
name="stop"
|
name="stop"
|
||||||
timeout="20s"
|
timeout="20s"
|
||||||
/>
|
/>
|
||||||
</operations>
|
</operations>
|
||||||
</primitive>
|
</primitive>
|
||||||
'';
|
'')
|
||||||
|
res.virtualIps;
|
||||||
|
|
||||||
mkSystemdResource = res: ''
|
mkSystemdResource = res: ''
|
||||||
<primitive id="${res.systemdName}" class="systemd" type="${res.systemdName}">
|
<primitive id="${res.systemdName}" class="systemd" type="${res.systemdName}">
|
||||||
|
@ -115,25 +135,40 @@ in {
|
||||||
</primitive>
|
</primitive>
|
||||||
'';
|
'';
|
||||||
|
|
||||||
mkConstraint = first: res: ''
|
mkConstraint = res: first: let
|
||||||
|
firstName =
|
||||||
|
if isAttrs first
|
||||||
|
then first.systemdName
|
||||||
|
else first;
|
||||||
|
in ''
|
||||||
<rsc_order
|
<rsc_order
|
||||||
id="order-${res.systemdName}"
|
id="order-${res.systemdName}-${firstName}"
|
||||||
first="${first}"
|
first="${firstName}"
|
||||||
then="${res.systemdName}"
|
then="${res.systemdName}"
|
||||||
kind="Mandatory"
|
kind="Mandatory"
|
||||||
/>
|
/>
|
||||||
<rsc_colocation
|
<rsc_colocation
|
||||||
id="colocate-${res.systemdName}"
|
id="colocate-${res.systemdName}-${firstName}"
|
||||||
rsc="${first}"
|
rsc="${firstName}"
|
||||||
with-rsc="${res.systemdName}"
|
with-rsc="${res.systemdName}"
|
||||||
score="INFINITY"
|
score="INFINITY"
|
||||||
/>
|
/>
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
mkDependsOn = res: let
|
||||||
|
mkConstraint' = first:
|
||||||
|
mkConstraint res first;
|
||||||
|
in
|
||||||
|
concatMapStringsSep "\n" mkConstraint' res.dependsOn;
|
||||||
|
|
||||||
mkVipConstraint = res:
|
mkVipConstraint = res:
|
||||||
|
concatMapStringsSep "\n" (
|
||||||
|
vip:
|
||||||
mkConstraint
|
mkConstraint
|
||||||
(res.systemdName + "vip")
|
res
|
||||||
res;
|
"${res.systemdName}-${vip.id}-vip"
|
||||||
|
)
|
||||||
|
res.virtualIps;
|
||||||
|
|
||||||
# If we're updating resources we have to kill constraints to add new resources
|
# If we're updating resources we have to kill constraints to add new resources
|
||||||
constraintsEmpty = toFile "constraints.xml" ''
|
constraintsEmpty = toFile "constraints.xml" ''
|
||||||
|
@ -143,11 +178,11 @@ in {
|
||||||
|
|
||||||
resEnabled = filterAttrs (n: v: v.enable) cfg.resources;
|
resEnabled = filterAttrs (n: v: v.enable) cfg.resources;
|
||||||
|
|
||||||
resWithIp = filterAttrs (n: v: ! isNull v.virtualIp) resEnabled;
|
resWithIp = filterAttrs (n: v: ! isNull v.virtualIps) resEnabled;
|
||||||
|
|
||||||
resources = toFile "resources.xml" ''
|
resources = toFile "resources.xml" ''
|
||||||
<resources>
|
<resources>
|
||||||
${concatMapStringsSep "\n" mkVirtIp (attrValues resWithIp)}
|
${concatMapStringsSep "\n" mkVirtIps (attrValues resWithIp)}
|
||||||
${concatMapStringsSep "\n" mkSystemdResource (attrValues resEnabled)}
|
${concatMapStringsSep "\n" mkSystemdResource (attrValues resEnabled)}
|
||||||
</resources>
|
</resources>
|
||||||
'';
|
'';
|
||||||
|
@ -155,6 +190,7 @@ in {
|
||||||
constraints = toFile "constraints.xml" ''
|
constraints = toFile "constraints.xml" ''
|
||||||
<constraints>
|
<constraints>
|
||||||
${concatMapStringsSep "\n" mkVipConstraint (attrValues resWithIp)}
|
${concatMapStringsSep "\n" mkVipConstraint (attrValues resWithIp)}
|
||||||
|
${concatMapStringsSep "\n" mkDependsOn (attrValues resEnabled)}
|
||||||
</constraints>
|
</constraints>
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue