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