diff options
Diffstat (limited to 'modules/private')
-rw-r--r-- | modules/private/environment.nix | 8 | ||||
-rw-r--r-- | modules/private/monitoring/default.nix | 6 | ||||
-rw-r--r-- | modules/private/monitoring/objects_common.nix | 3 | ||||
-rw-r--r-- | modules/private/monitoring/objects_eban.nix | 60 | ||||
-rw-r--r-- | modules/private/monitoring/objects_phare.nix | 1 | ||||
-rw-r--r-- | modules/private/monitoring/objects_tiboqorl-fr.nix | 1 | ||||
-rw-r--r-- | modules/private/monitoring/objects_ulminfo-fr.nix | 1 | ||||
-rwxr-xr-x | modules/private/monitoring/plugins/notify_eban_url | 13 | ||||
-rw-r--r-- | modules/private/monitoring/status.nix | 7 | ||||
-rwxr-xr-x | modules/private/monitoring/status/app.py | 35 | ||||
-rw-r--r-- | modules/private/system.nix | 3 |
11 files changed, 121 insertions, 17 deletions
diff --git a/modules/private/environment.nix b/modules/private/environment.nix index e79feec..490a405 100644 --- a/modules/private/environment.nix +++ b/modules/private/environment.nix | |||
@@ -558,6 +558,14 @@ in | |||
558 | }; | 558 | }; |
559 | }; | 559 | }; |
560 | }; | 560 | }; |
561 | eban = mkOption { | ||
562 | description = "Eban credentials for webhook"; | ||
563 | type = submodule { | ||
564 | options = { | ||
565 | password = mkOption { type = str; description = "Password"; }; | ||
566 | }; | ||
567 | }; | ||
568 | }; | ||
561 | nrdp_tokens = mkOption { type = listOf str; description = "Tokens allowed to push status update"; }; | 569 | nrdp_tokens = mkOption { type = listOf str; description = "Tokens allowed to push status update"; }; |
562 | slack_url = mkOption { type = str; description = "Slack webhook url to push status update"; }; | 570 | slack_url = mkOption { type = str; description = "Slack webhook url to push status update"; }; |
563 | slack_channel = mkOption { type = str; description = "Slack channel to push status update"; }; | 571 | slack_channel = mkOption { type = str; description = "Slack channel to push status update"; }; |
diff --git a/modules/private/monitoring/default.nix b/modules/private/monitoring/default.nix index a298f92..73e4275 100644 --- a/modules/private/monitoring/default.nix +++ b/modules/private/monitoring/default.nix | |||
@@ -78,6 +78,9 @@ let | |||
78 | wrapProgram $out/notify_by_slack --prefix PATH : ${lib.makeBinPath [ | 78 | wrapProgram $out/notify_by_slack --prefix PATH : ${lib.makeBinPath [ |
79 | pkgs.curl pkgs.jq | 79 | pkgs.curl pkgs.jq |
80 | ]} | 80 | ]} |
81 | wrapProgram $out/notify_eban_url --prefix PATH : ${lib.makeBinPath [ | ||
82 | pkgs.curl | ||
83 | ]} | ||
81 | wrapProgram $out/check_ovh_sms --prefix PATH : ${lib.makeBinPath [ | 84 | wrapProgram $out/check_ovh_sms --prefix PATH : ${lib.makeBinPath [ |
82 | (pkgs.python3.withPackages (ps: [ps.ovh])) | 85 | (pkgs.python3.withPackages (ps: [ps.ovh])) |
83 | ]} | 86 | ]} |
@@ -157,7 +160,7 @@ let | |||
157 | }; | 160 | }; |
158 | otherObjects = map | 161 | otherObjects = map |
159 | (n: (pkgs.callPackage (./. + "/objects_" + n + ".nix") { inherit emailCheck; })) | 162 | (n: (pkgs.callPackage (./. + "/objects_" + n + ".nix") { inherit emailCheck; })) |
160 | [ "ulminfo-fr" "phare" ]; | 163 | [ "ulminfo-fr" "phare" "eban" ]; |
161 | masterObjects = pkgs.callPackage ./objects_master.nix { inherit config; }; | 164 | masterObjects = pkgs.callPackage ./objects_master.nix { inherit config; }; |
162 | commonObjects = pkgs.callPackage ./objects_common.nix ({ | 165 | commonObjects = pkgs.callPackage ./objects_common.nix ({ |
163 | master = cfg.master; | 166 | master = cfg.master; |
@@ -326,6 +329,7 @@ in | |||
326 | config.myEnv.monitoring.ovh_sms.consumer_key | 329 | config.myEnv.monitoring.ovh_sms.consumer_key |
327 | config.myEnv.monitoring.ovh_sms.account | 330 | config.myEnv.monitoring.ovh_sms.account |
328 | ]} | 331 | ]} |
332 | $USER210$=${config.myEnv.monitoring.eban.password} | ||
329 | ''; | 333 | ''; |
330 | objectDefs = toObjects commonObjects | 334 | objectDefs = toObjects commonObjects |
331 | + toObjects hostObjects | 335 | + toObjects hostObjects |
diff --git a/modules/private/monitoring/objects_common.nix b/modules/private/monitoring/objects_common.nix index 7f553a0..df378b5 100644 --- a/modules/private/monitoring/objects_common.nix +++ b/modules/private/monitoring/objects_common.nix | |||
@@ -34,6 +34,7 @@ in | |||
34 | use = "linux-server"; | 34 | use = "linux-server"; |
35 | hostgroups = "webstatus-hosts"; | 35 | hostgroups = "webstatus-hosts"; |
36 | _webstatus_name = hostName; | 36 | _webstatus_name = hostName; |
37 | _webstatus_vhost = "status.immae.eu"; | ||
37 | }; | 38 | }; |
38 | }; | 39 | }; |
39 | service = [ | 40 | service = [ |
@@ -155,6 +156,8 @@ in | |||
155 | # $OVE is to force naemon to run via shell instead of execve which fails here | 156 | # $OVE is to force naemon to run via shell instead of execve which fails here |
156 | notify-service-by-email = "ADMINEMAIL=\"$ADMINEMAIL$\" SERVICENOTIFICATIONID=\"$SERVICENOTIFICATIONID$\" SERVICEDESC=\"$SERVICEDESC$\" SERVICESTATE=\"$SERVICESTATE$\" SERVICEOUTPUT=\"$SERVICEOUTPUT$\" $USER2$/notify_by_email service \"$NOTIFICATIONTYPE$\" \"$HOSTALIAS$\" \"$LONGDATETIME$\" \"$CONTACTEMAIL$\" $OVE"; | 157 | notify-service-by-email = "ADMINEMAIL=\"$ADMINEMAIL$\" SERVICENOTIFICATIONID=\"$SERVICENOTIFICATIONID$\" SERVICEDESC=\"$SERVICEDESC$\" SERVICESTATE=\"$SERVICESTATE$\" SERVICEOUTPUT=\"$SERVICEOUTPUT$\" $USER2$/notify_by_email service \"$NOTIFICATIONTYPE$\" \"$HOSTALIAS$\" \"$LONGDATETIME$\" \"$CONTACTEMAIL$\" $OVE"; |
157 | notify-by-slack = "HOST=\"$HOSTALIAS$\" SERVICESTATE=\"$SERVICESTATE$\" SERVICEDESC=\"$SERVICEDESC$\" SERVICEOUTPUT=\"$SERVICEOUTPUT$\" $USER2$/notify_by_slack \"$ARG1$\" \"$ARG2$\""; | 158 | notify-by-slack = "HOST=\"$HOSTALIAS$\" SERVICESTATE=\"$SERVICESTATE$\" SERVICEDESC=\"$SERVICEDESC$\" SERVICEOUTPUT=\"$SERVICEOUTPUT$\" $USER2$/notify_by_slack \"$ARG1$\" \"$ARG2$\""; |
159 | notify-host-eban-url = "STATUS_NAME=\"Server\" PASSWORD=\"$USER210$\" HOSTSTATE=\"$HOSTSTATE$\" $USER2$/notify_eban_url"; | ||
160 | notify-service-eban-url = "STATUS_NAME=\"$_SERVICEWEBSTATUS_NAME$\" PASSWORD=\"$USER210$\" SERVICESTATE=\"$SERVICESTATE$\" $USER2$/notify_eban_url"; | ||
158 | 161 | ||
159 | notify-master = "$USER2$/send_nrdp.sh -u \"$USER200$\" -t \"$USER201$\" -H \"$HOSTADDRESS$\" -s \"$SERVICEDESC$\" -S \"$SERVICESTATEID$\" -o \"$SERVICEOUTPUT$ | $SERVICEPERFDATA$\""; | 162 | notify-master = "$USER2$/send_nrdp.sh -u \"$USER200$\" -t \"$USER201$\" -H \"$HOSTADDRESS$\" -s \"$SERVICEDESC$\" -S \"$SERVICESTATEID$\" -o \"$SERVICEOUTPUT$ | $SERVICEPERFDATA$\""; |
160 | }; | 163 | }; |
diff --git a/modules/private/monitoring/objects_eban.nix b/modules/private/monitoring/objects_eban.nix new file mode 100644 index 0000000..659b0ec --- /dev/null +++ b/modules/private/monitoring/objects_eban.nix | |||
@@ -0,0 +1,60 @@ | |||
1 | { ... }: | ||
2 | let | ||
3 | serviceTemplate = rest: { | ||
4 | host_name = "eban.bzh"; | ||
5 | use = "external-web-service"; | ||
6 | contacts = "eban"; | ||
7 | contact_groups = "null"; | ||
8 | check_interval = "15"; | ||
9 | |||
10 | servicegroups = "webstatus-resources"; | ||
11 | } // rest; | ||
12 | in | ||
13 | { | ||
14 | contact = { | ||
15 | eban = { | ||
16 | use = "generic-contact"; | ||
17 | host_notification_commands = "notify-host-eban-url"; | ||
18 | service_notification_commands = "notify-service-eban-url"; | ||
19 | }; | ||
20 | }; | ||
21 | host = { | ||
22 | "eban.bzh" = { | ||
23 | alias = "eban.bzh"; | ||
24 | address = "eban.bzh"; | ||
25 | use = "linux-server"; | ||
26 | hostgroups = "webstatus-hosts"; | ||
27 | contacts = "eban"; | ||
28 | contact_groups = "null"; | ||
29 | _webstatus_name = "Eban"; | ||
30 | _webstatus_vhost = "status.eban.bzh"; | ||
31 | }; | ||
32 | }; | ||
33 | service = [ | ||
34 | (serviceTemplate { | ||
35 | service_description = "Eban website is up and running"; | ||
36 | check_command = ["check_https" "eban.bzh" "/" "<title>"]; | ||
37 | _webstatus_name = "Main Website"; | ||
38 | _webstatus_url = "https://eban.bzh/"; | ||
39 | }) | ||
40 | (serviceTemplate { | ||
41 | service_description = "Eban blog is up and running"; | ||
42 | check_command = ["check_https" "blog.eban.bzh" "/" "<title>"]; | ||
43 | _webstatus_name = "Blog"; | ||
44 | _webstatus_url = "https://blog.eban.bzh/"; | ||
45 | }) | ||
46 | (serviceTemplate { | ||
47 | service_description = "Eban gitea is up and running"; | ||
48 | check_command = ["check_https" "git.eban.bzh" "/" "<title>"]; | ||
49 | _webstatus_name = "Git"; | ||
50 | _webstatus_url = "https://git.eban.bzh/"; | ||
51 | }) | ||
52 | (serviceTemplate { | ||
53 | service_description = "Eban Cloud is up and running"; | ||
54 | check_command = ["check_https" "cloud.eban.bzh" "/" "<title>"]; | ||
55 | |||
56 | _webstatus_name = "Cloud"; | ||
57 | _webstatus_url = "https://cloud.eban.bzh/"; | ||
58 | }) | ||
59 | ]; | ||
60 | } | ||
diff --git a/modules/private/monitoring/objects_phare.nix b/modules/private/monitoring/objects_phare.nix index a00e5e8..a61b46e 100644 --- a/modules/private/monitoring/objects_phare.nix +++ b/modules/private/monitoring/objects_phare.nix | |||
@@ -7,6 +7,7 @@ | |||
7 | use = "linux-server"; | 7 | use = "linux-server"; |
8 | hostgroups = "webstatus-hosts"; | 8 | hostgroups = "webstatus-hosts"; |
9 | _webstatus_name = "phare"; | 9 | _webstatus_name = "phare"; |
10 | _webstatus_vhost = "status.immae.eu"; | ||
10 | }; | 11 | }; |
11 | }; | 12 | }; |
12 | service = [ | 13 | service = [ |
diff --git a/modules/private/monitoring/objects_tiboqorl-fr.nix b/modules/private/monitoring/objects_tiboqorl-fr.nix index c3851b5..77403ba 100644 --- a/modules/private/monitoring/objects_tiboqorl-fr.nix +++ b/modules/private/monitoring/objects_tiboqorl-fr.nix | |||
@@ -22,6 +22,7 @@ in | |||
22 | contact_groups = "tiboqorl"; | 22 | contact_groups = "tiboqorl"; |
23 | hostgroups = "webstatus-hosts"; | 23 | hostgroups = "webstatus-hosts"; |
24 | _webstatus_name = "tiboqorl"; | 24 | _webstatus_name = "tiboqorl"; |
25 | _webstatus_vhost = "status.immae.eu"; | ||
25 | }; | 26 | }; |
26 | }; | 27 | }; |
27 | service = [ | 28 | service = [ |
diff --git a/modules/private/monitoring/objects_ulminfo-fr.nix b/modules/private/monitoring/objects_ulminfo-fr.nix index b970ecd..574e0e3 100644 --- a/modules/private/monitoring/objects_ulminfo-fr.nix +++ b/modules/private/monitoring/objects_ulminfo-fr.nix | |||
@@ -7,6 +7,7 @@ | |||
7 | use = "linux-server"; | 7 | use = "linux-server"; |
8 | hostgroups = "webstatus-hosts"; | 8 | hostgroups = "webstatus-hosts"; |
9 | _webstatus_name = "ulminfo"; | 9 | _webstatus_name = "ulminfo"; |
10 | _webstatus_vhost = "status.immae.eu"; | ||
10 | }; | 11 | }; |
11 | }; | 12 | }; |
12 | service = [ | 13 | service = [ |
diff --git a/modules/private/monitoring/plugins/notify_eban_url b/modules/private/monitoring/plugins/notify_eban_url new file mode 100755 index 0000000..431e320 --- /dev/null +++ b/modules/private/monitoring/plugins/notify_eban_url | |||
@@ -0,0 +1,13 @@ | |||
1 | #!/usr/bin/env bash | ||
2 | |||
3 | PASS=$(echo "$PASSWORD" | base64 -d) | ||
4 | |||
5 | if [ "$SERVICESTATE" = "CRITICAL" -o "$SERVICESTATE" = "UNKNOWN" -o "$HOSTSTATE" = "DOWN" -o "$HOSTSTATE" = "UNREACHABLE" ]; then | ||
6 | action=downAlert | ||
7 | elif [ "$SERVICESTATE" = "OK" -o "$HOSTSTATE" = "UP" ]; then | ||
8 | action=upAlert | ||
9 | fi | ||
10 | |||
11 | if [ -n "$action" ]; then | ||
12 | curl -X GET -G --data-urlencode "service=$STATUS_NAME" --data-urlencode "mdp=$PASS" https://infra.eban.bzh/$action | ||
13 | fi | ||
diff --git a/modules/private/monitoring/status.nix b/modules/private/monitoring/status.nix index 4ca0327..73f4749 100644 --- a/modules/private/monitoring/status.nix +++ b/modules/private/monitoring/status.nix | |||
@@ -32,6 +32,12 @@ | |||
32 | upstreams."netdata".extraConfig = '' | 32 | upstreams."netdata".extraConfig = '' |
33 | keepalive 64; | 33 | keepalive 64; |
34 | ''; | 34 | ''; |
35 | virtualHosts."status.eban.bzh" = { | ||
36 | acmeRoot = config.myServices.certificates.webroot; | ||
37 | useACMEHost = name; | ||
38 | forceSSL = true; | ||
39 | locations."/".proxyPass = "http://unix:/run/naemon-status/socket.sock:/"; | ||
40 | }; | ||
35 | virtualHosts."status.immae.eu" = { | 41 | virtualHosts."status.immae.eu" = { |
36 | acmeRoot = config.myServices.certificates.webroot; | 42 | acmeRoot = config.myServices.certificates.webroot; |
37 | useACMEHost = name; | 43 | useACMEHost = name; |
@@ -60,6 +66,7 @@ | |||
60 | }; | 66 | }; |
61 | security.acme.certs."${name}" = { | 67 | security.acme.certs."${name}" = { |
62 | extraDomains."status.immae.eu" = null; | 68 | extraDomains."status.immae.eu" = null; |
69 | extraDomains."status.eban.bzh" = null; | ||
63 | user = config.services.nginx.user; | 70 | user = config.services.nginx.user; |
64 | group = config.services.nginx.group; | 71 | group = config.services.nginx.group; |
65 | }; | 72 | }; |
diff --git a/modules/private/monitoring/status/app.py b/modules/private/monitoring/status/app.py index b1d419c..ff92891 100755 --- a/modules/private/monitoring/status/app.py +++ b/modules/private/monitoring/status/app.py | |||
@@ -55,33 +55,34 @@ def get_lq(request): | |||
55 | return b"".join(chunks).decode() | 55 | return b"".join(chunks).decode() |
56 | 56 | ||
57 | class Host: | 57 | class Host: |
58 | def __init__(self, name, alias, status, webname): | 58 | def __init__(self, name, alias, status, webname, vhost): |
59 | self.name = name | 59 | self.name = name |
60 | self.alias = alias | 60 | self.alias = alias |
61 | self.webname = webname or alias | 61 | self.webname = webname or alias |
62 | self.vhost = vhost | ||
62 | self.status = status | 63 | self.status = status |
63 | self.services = [] | 64 | self.services = [] |
64 | 65 | ||
65 | @classmethod | 66 | @classmethod |
66 | def parse_hosts(cls, payload): | 67 | def parse_hosts(cls, payload, vhost): |
67 | parsed = [cls.parse(p) for p in json.loads(payload)] | 68 | parsed = filter(lambda x: x.vhost == vhost, [cls.parse(p) for p in json.loads(payload)]) |
68 | return {p.name: p for p in parsed} | 69 | return {p.name: p for p in parsed} |
69 | 70 | ||
70 | @classmethod | 71 | @classmethod |
71 | def parse(cls, payload): | 72 | def parse(cls, payload): |
72 | return cls(payload[0], payload[1], HOST_STATUS[payload[2]], payload[3].get("WEBSTATUS_NAME")) | 73 | return cls(payload[0], payload[1], HOST_STATUS[payload[2]], payload[3].get("WEBSTATUS_NAME"), payload[3].get("WEBSTATUS_VHOST")) |
73 | 74 | ||
74 | def __repr__(self): | 75 | def __repr__(self): |
75 | return "Host {}: {} ({})".format(self.name, self.alias, self.webname) | 76 | return "Host {}: {} ({})".format(self.name, self.alias, self.webname) |
76 | 77 | ||
77 | @classmethod | 78 | @classmethod |
78 | def query(cls): | 79 | def query(cls, vhost): |
79 | answer = get_lq("""GET hosts | 80 | answer = get_lq("""GET hosts |
80 | Filter: groups >= webstatus-hosts | 81 | Filter: groups >= webstatus-hosts |
81 | Columns: name alias state custom_variables | 82 | Columns: name alias state custom_variables |
82 | OutputFormat: json | 83 | OutputFormat: json |
83 | """) | 84 | """) |
84 | return cls.parse_hosts(answer) | 85 | return cls.parse_hosts(answer, vhost) |
85 | 86 | ||
86 | def fill_services(self, services): | 87 | def fill_services(self, services): |
87 | self.services = [service for service in services if service.host == self.name] | 88 | self.services = [service for service in services if service.host == self.name] |
@@ -110,8 +111,8 @@ OutputFormat: json | |||
110 | """) | 111 | """) |
111 | return cls.parse_groups(answer) | 112 | return cls.parse_groups(answer) |
112 | 113 | ||
113 | def fill_services(self, services): | 114 | def fill_services(self, services, hosts): |
114 | self.services = [service for service in services if any([group == self.name for group in service.groups])] | 115 | self.services = [service for service in services if any([group == self.name for group in service.groups]) and service.host in hosts] |
115 | 116 | ||
116 | def __repr__(self): | 117 | def __repr__(self): |
117 | return "ServiceGroup {}: {}".format(self.name, self.alias) | 118 | return "ServiceGroup {}: {}".format(self.name, self.alias) |
@@ -158,15 +159,15 @@ OutputFormat: json | |||
158 | def __repr__(self): | 159 | def __repr__(self): |
159 | return "Service {}: {}".format(self.name, self.webname) | 160 | return "Service {}: {}".format(self.name, self.webname) |
160 | 161 | ||
161 | def get_infos(): | 162 | def get_infos(vhost): |
162 | hosts = Host.query() | 163 | hosts = Host.query(vhost) |
163 | servicegroups = ServiceGroup.query() | 164 | servicegroups = ServiceGroup.query() |
164 | services = Service.query() | 165 | services = Service.query() |
165 | 166 | ||
166 | for host in hosts: | 167 | for host in hosts: |
167 | hosts[host].fill_services(services) | 168 | hosts[host].fill_services(services) |
168 | for group in servicegroups: | 169 | for group in servicegroups: |
169 | servicegroups[group].fill_services(services) | 170 | servicegroups[group].fill_services(services, hosts) |
170 | return (hosts, servicegroups, services) | 171 | return (hosts, servicegroups, services) |
171 | 172 | ||
172 | TEMPLATE='''<?xml version="1.0" encoding="UTF-8"?> | 173 | TEMPLATE='''<?xml version="1.0" encoding="UTF-8"?> |
@@ -254,12 +255,14 @@ TEMPLATE='''<?xml version="1.0" encoding="UTF-8"?> | |||
254 | {% endfor %} | 255 | {% endfor %} |
255 | {%- endfor %} | 256 | {%- endfor %} |
256 | 257 | ||
258 | {%- for group in servicegroups.values() if group.services and group.name != "webstatus-resources" %} | ||
259 | {%- if loop.first %} | ||
257 | <h2>Services</h2> | 260 | <h2>Services</h2> |
258 | <div id="services"> | 261 | <div id="services"> |
259 | {%- for group in servicegroups.values() if group.services and group.name != "webstatus-resources" %} | 262 | {%- endif %} |
260 | <div class="servicegroup"> | 263 | <div class="servicegroup"> |
261 | <h3 class="servicegroup_title">{{ group.alias }}</h3> | 264 | <h3 class="servicegroup_title">{{ group.alias }}</h3> |
262 | {%- for service in group.services -%} | 265 | {%- for service in group.services if service.host in hosts -%} |
263 | {%- if loop.first %} | 266 | {%- if loop.first %} |
264 | <ul class="services"> | 267 | <ul class="services"> |
265 | {% endif %} | 268 | {% endif %} |
@@ -281,8 +284,10 @@ TEMPLATE='''<?xml version="1.0" encoding="UTF-8"?> | |||
281 | {% endif %} | 284 | {% endif %} |
282 | {%- endfor -%} | 285 | {%- endfor -%} |
283 | </div> | 286 | </div> |
284 | {%- endfor %} | 287 | {%- if loop.last %} |
285 | </div> | 288 | </div> |
289 | {% endif %} | ||
290 | {%- endfor %} | ||
286 | </body> | 291 | </body> |
287 | </html> | 292 | </html> |
288 | ''' | 293 | ''' |
@@ -307,7 +312,7 @@ def live(): | |||
307 | 312 | ||
308 | @app.route("/", methods=["GET"]) | 313 | @app.route("/", methods=["GET"]) |
309 | def get(): | 314 | def get(): |
310 | (hosts, servicegroups, services) = get_infos() | 315 | (hosts, servicegroups, services) = get_infos(request.host) |
311 | resp = make_response(render_template_string(TEMPLATE, hosts=hosts, servicegroups=servicegroups)) | 316 | resp = make_response(render_template_string(TEMPLATE, hosts=hosts, servicegroups=servicegroups)) |
312 | resp.content_type = "text/html" | 317 | resp.content_type = "text/html" |
313 | return resp | 318 | return resp |
diff --git a/modules/private/system.nix b/modules/private/system.nix index 71a49e3..0e72d99 100644 --- a/modules/private/system.nix +++ b/modules/private/system.nix | |||
@@ -26,7 +26,8 @@ | |||
26 | ]; | 26 | ]; |
27 | 27 | ||
28 | services.journald.extraConfig = '' | 28 | services.journald.extraConfig = '' |
29 | MaxLevelStore=warning | 29 | #Should be "warning" but disabled for now, it prevents anything from being stored |
30 | MaxLevelStore=info | ||
30 | MaxRetentionSec=1year | 31 | MaxRetentionSec=1year |
31 | ''; | 32 | ''; |
32 | 33 | ||