1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8 cfg = config.services.corosync;
9in
10{
11 # interface
12 options.services.corosync = {
13 enable = lib.mkEnableOption "corosync";
14
15 package = lib.mkPackageOption pkgs "corosync" { };
16
17 clusterName = lib.mkOption {
18 type = lib.types.str;
19 default = "nixcluster";
20 description = "Name of the corosync cluster.";
21 };
22
23 extraOptions = lib.mkOption {
24 type = with lib.types; listOf str;
25 default = [ ];
26 description = "Additional options with which to start corosync.";
27 };
28
29 nodelist = lib.mkOption {
30 description = "Corosync nodelist: all cluster members.";
31 default = [ ];
32 type =
33 with lib.types;
34 listOf (submodule {
35 options = {
36 nodeid = lib.mkOption {
37 type = int;
38 description = "Node ID number";
39 };
40 name = lib.mkOption {
41 type = str;
42 description = "Node name";
43 };
44 ring_addrs = lib.mkOption {
45 type = listOf str;
46 description = "List of addresses, one for each ring.";
47 };
48 };
49 });
50 };
51 };
52
53 # implementation
54 config = lib.mkIf cfg.enable {
55 environment.systemPackages = [ cfg.package ];
56
57 environment.etc."corosync/corosync.conf".text = ''
58 totem {
59 version: 2
60 secauth: on
61 cluster_name: ${cfg.clusterName}
62 transport: knet
63 }
64
65 nodelist {
66 ${lib.concatMapStrings (
67 {
68 nodeid,
69 name,
70 ring_addrs,
71 }:
72 ''
73 node {
74 nodeid: ${toString nodeid}
75 name: ${name}
76 ${lib.concatStrings (
77 lib.imap0 (i: addr: ''
78 ring${toString i}_addr: ${addr}
79 '') ring_addrs
80 )}
81 }
82 ''
83 ) cfg.nodelist}
84 }
85
86 quorum {
87 # only corosync_votequorum is supported
88 provider: corosync_votequorum
89 wait_for_all: 0
90 ${lib.optionalString (builtins.length cfg.nodelist < 3) ''
91 two_node: 1
92 ''}
93 }
94
95 logging {
96 to_syslog: yes
97 }
98 '';
99
100 environment.etc."corosync/uidgid.d/root".text = ''
101 # allow pacemaker connection by root
102 uidgid {
103 uid: 0
104 gid: 0
105 }
106 '';
107
108 systemd.packages = [ cfg.package ];
109 systemd.services.corosync = {
110 wantedBy = [ "multi-user.target" ];
111 serviceConfig = {
112 StateDirectory = "corosync";
113 StateDirectoryMode = "0700";
114 };
115 };
116
117 environment.etc."sysconfig/corosync".text = lib.optionalString (cfg.extraOptions != [ ]) ''
118 COROSYNC_OPTIONS="${lib.escapeShellArgs cfg.extraOptions}"
119 '';
120 };
121}