1# Systemd services for openvswitch
2
3{
4 config,
5 lib,
6 pkgs,
7 ...
8}:
9
10with lib;
11
12let
13 cfg = config.virtualisation.vswitch;
14
15in
16{
17
18 options.virtualisation.vswitch = {
19 enable = mkOption {
20 type = types.bool;
21 default = false;
22 description = ''
23 Whether to enable Open vSwitch. A configuration daemon (ovs-server)
24 will be started.
25 '';
26 };
27
28 resetOnStart = mkOption {
29 type = types.bool;
30 default = false;
31 description = ''
32 Whether to reset the Open vSwitch configuration database to a default
33 configuration on every start of the systemd `ovsdb.service`.
34 '';
35 };
36
37 package = mkPackageOption pkgs "openvswitch" { };
38 };
39
40 config = mkIf cfg.enable (
41 let
42
43 # Where the communication sockets live
44 runDir = "/run/openvswitch";
45
46 # The path to the an initialized version of the database
47 db = pkgs.stdenv.mkDerivation {
48 name = "vswitch.db";
49 dontUnpack = true;
50 buildPhase = "true";
51 buildInputs = with pkgs; [
52 cfg.package
53 ];
54 installPhase = "mkdir -p $out";
55 };
56
57 in
58 {
59 environment.systemPackages = [ cfg.package ];
60 boot.kernelModules = [
61 "tun"
62 "openvswitch"
63 ];
64
65 boot.extraModulePackages = [ cfg.package ];
66
67 systemd.services.ovsdb = {
68 description = "Open_vSwitch Database Server";
69 wantedBy = [ "multi-user.target" ];
70 after = [ "systemd-udev-settle.service" ];
71 path = [ cfg.package ];
72 restartTriggers = [
73 db
74 cfg.package
75 ];
76 # Create the config database
77 preStart = ''
78 mkdir -p ${runDir}
79 mkdir -p /var/db/openvswitch
80 chmod +w /var/db/openvswitch
81 ${optionalString cfg.resetOnStart "rm -f /var/db/openvswitch/conf.db"}
82 if [[ ! -e /var/db/openvswitch/conf.db ]]; then
83 ${cfg.package}/bin/ovsdb-tool create \
84 "/var/db/openvswitch/conf.db" \
85 "${cfg.package}/share/openvswitch/vswitch.ovsschema"
86 fi
87 chmod -R +w /var/db/openvswitch
88 if ${cfg.package}/bin/ovsdb-tool needs-conversion /var/db/openvswitch/conf.db | grep -q "yes"
89 then
90 echo "Performing database upgrade"
91 ${cfg.package}/bin/ovsdb-tool convert /var/db/openvswitch/conf.db
92 else
93 echo "Database already up to date"
94 fi
95 '';
96 serviceConfig = {
97 ExecStart = ''
98 ${cfg.package}/bin/ovsdb-server \
99 --remote=punix:${runDir}/db.sock \
100 --private-key=db:Open_vSwitch,SSL,private_key \
101 --certificate=db:Open_vSwitch,SSL,certificate \
102 --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \
103 --unixctl=ovsdb.ctl.sock \
104 --pidfile=/run/openvswitch/ovsdb.pid \
105 --detach \
106 /var/db/openvswitch/conf.db
107 '';
108 Restart = "always";
109 RestartSec = 3;
110 PIDFile = "/run/openvswitch/ovsdb.pid";
111 # Use service type 'forking' to correctly determine when ovsdb-server is ready.
112 Type = "forking";
113 };
114 postStart = ''
115 ${cfg.package}/bin/ovs-vsctl --timeout 3 --retry --no-wait init
116 '';
117 };
118
119 systemd.services.ovs-vswitchd = {
120 description = "Open_vSwitch Daemon";
121 wantedBy = [ "multi-user.target" ];
122 bindsTo = [ "ovsdb.service" ];
123 after = [ "ovsdb.service" ];
124 path = [ cfg.package ];
125 serviceConfig = {
126 ExecStart = ''
127 ${cfg.package}/bin/ovs-vswitchd \
128 --pidfile=/run/openvswitch/ovs-vswitchd.pid \
129 --detach
130 '';
131 PIDFile = "/run/openvswitch/ovs-vswitchd.pid";
132 # Use service type 'forking' to correctly determine when vswitchd is ready.
133 Type = "forking";
134 Restart = "always";
135 RestartSec = 3;
136 };
137 };
138
139 }
140 );
141
142 imports = [
143 (mkRemovedOptionModule [ "virtualisation" "vswitch" "ipsec" ] ''
144 OpenVSwitch IPSec functionality has been removed, because it depended on racoon,
145 which was removed from nixpkgs, because it was abanoded upstream.
146 '')
147 ];
148
149 meta.maintainers = with maintainers; [ netixx ];
150
151}