Skip to content

Commit c39b463

Browse files
committed
check datastore size and garbage collection status
1 parent eae3d7c commit c39b463

File tree

6 files changed

+346
-0
lines changed

6 files changed

+346
-0
lines changed

agent_based/proxmox_bs.py

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
4+
from .agent_based_api.v1 import (
5+
get_value_store,
6+
register,
7+
Service,
8+
ServiceLabel,
9+
State,
10+
Result,
11+
)
12+
from .utils import df
13+
import re
14+
import json
15+
16+
proxmox_bs_subsection_start = re.compile("^===")
17+
proxmox_bs_subsection_int = re.compile("===.*$")
18+
proxmox_bs_subsection_end = re.compile("^=")
19+
20+
21+
def proxmox_bs_subsections_discovery(section):
22+
active = False
23+
24+
name = None
25+
key = None
26+
content = ""
27+
key_i = 0
28+
29+
for line in section:
30+
line = ' '.join(''.join(_) for _ in line)
31+
if active and proxmox_bs_subsection_end.match(line):
32+
active = False
33+
yield name, key, content
34+
key = None
35+
name = None
36+
content = ""
37+
if (not active) and proxmox_bs_subsection_start.match(line):
38+
active = True
39+
rest = str(line)[3:].strip()
40+
s_rest = rest.split('===')
41+
name = s_rest[0]
42+
if len(s_rest) == 2:
43+
key = s_rest[1]
44+
key_i += 1
45+
content = ""
46+
continue
47+
if active:
48+
content += str(line).rstrip()
49+
50+
51+
def proxmox_bs_subsections_checks(section):
52+
active = False
53+
54+
name = None
55+
key = None
56+
content = ""
57+
key_i = 0
58+
59+
for line in section:
60+
line = ' '.join(line)
61+
if active and proxmox_bs_subsection_end.match(line):
62+
active = False
63+
yield name, key, content
64+
key = None
65+
name = None
66+
content = ""
67+
if (not active) and proxmox_bs_subsection_start.match(line):
68+
active = True
69+
rest = line[3:].strip()
70+
s_rest = rest.split('===')
71+
name = s_rest[0].rstrip()
72+
if len(s_rest) == 2:
73+
key = s_rest[1]
74+
key_i += 1
75+
content = ""
76+
continue
77+
if active:
78+
content += line.rstrip()
79+
80+
81+
def proxmox_bs_discovery(section):
82+
for n, k, c in proxmox_bs_subsections_discovery(section):
83+
if n == "proxmox-backup-manager datastore list":
84+
for ds in json.loads(c):
85+
if "name" in ds:
86+
yield Service(
87+
item=ds["name"],
88+
labels=[ServiceLabel('pbs/datastore', 'yes')]
89+
)
90+
return
91+
92+
def proxmox_bs_checks(item, params, section):
93+
req_ok = True
94+
expected = []
95+
missing = []
96+
97+
upid = None
98+
upid_status = {}
99+
100+
gc_ok = False
101+
gc_running = False
102+
103+
running_tasks = []
104+
value_store = get_value_store()
105+
106+
for n, k, c in proxmox_bs_subsections_checks(section):
107+
if n == "proxmox-backup-manager task list":
108+
task_list = json.loads(c)
109+
for task in task_list:
110+
if ("starttime" in task) and ("endtime" not in task):
111+
running_tasks.append(task["upid"])
112+
if task.get("worker_id", None) is not None:
113+
if task.get("worker_id", None) == item:
114+
gc_running = True
115+
if n == "proxmox-backup-manager garbage-collection status":
116+
if k == item:
117+
gc = json.loads(c)
118+
if "upid" in gc:
119+
upid = gc["upid"]
120+
if (n == "proxmox-backup-client status") and (k == item):
121+
try:
122+
ds_status = json.loads(c)
123+
size_mb = int(ds_status["total"])/(1024**2)
124+
avail_mb = int(ds_status["avail"])/(1024**2)
125+
126+
yield from df.df_check_filesystem_single(
127+
value_store, item, size_mb, avail_mb,
128+
None, None, None, params
129+
)
130+
except:
131+
yield Result(
132+
state=State.UNKNOWN,
133+
summary="error checking datastore status"
134+
)
135+
if (n == "proxmox-backup-manager task log") and (k == upid):
136+
if "TASK OK" in c.strip()[-7:]:
137+
gc_ok = True
138+
139+
if n == "EOD":
140+
if gc_running:
141+
yield Result( state=State.OK, summary="GC running" )
142+
elif gc_ok:
143+
yield Result( state=State.OK, summary="GC ok" )
144+
elif upid == None:
145+
yield Result( state=State.UNKNOWN, summary="GC not run yet" )
146+
else:
147+
yield Result( state=State.WARN, summary="GC Task failed" )
148+
149+
150+
register.agent_section(
151+
name="proxmox_bs",
152+
#host_label_function = proxmox_bs_hostlabels,
153+
)
154+
155+
register.check_plugin(
156+
name="proxmox_bs",
157+
service_name="PBS Datastore %s",
158+
sections=["proxmox_bs"],
159+
discovery_function=proxmox_bs_discovery,
160+
check_function=proxmox_bs_checks,
161+
check_default_parameters=df.FILESYSTEM_DEFAULT_LEVELS,
162+
check_ruleset_name="filesystem",
163+
)
164+

agents/plugins/proxmox_bs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#!/bin/bash
2+
3+
inpath() {
4+
command -v "${1:?No command to test}" >/dev/null 2>&1
5+
}
6+
7+
printf "<<<proxmox_bs>>>\n"
8+
9+
printf "===requirements===\n"
10+
requirement() {
11+
inpath $1; RC=$?
12+
printf "$RC $1\n"
13+
}
14+
requirements() {
15+
RC=0
16+
while read -r req; do
17+
line=$( requirement $req )
18+
trc=$( printf "$line" | cut -d ' ' -f 1 )
19+
echo $line
20+
[ "$trc" != "0" ] && RC=1
21+
done
22+
return $RC
23+
}
24+
cat <<. | requirements || exit 0
25+
proxmox-backup-manager
26+
proxmox-backup-client
27+
jq
28+
.
29+
30+
$(< /etc/check_mk/proxmox_bs.env)
31+
32+
command_section() {
33+
PIPE=
34+
SECTION_POSTFIX=
35+
while [[ "$1" == -* ]]; do
36+
if [ "$1" == "-P" ]; then
37+
PIPE="${PIPE} | $2"
38+
shift 2
39+
fi
40+
if [ "$1" == "-t" ]; then
41+
PIPE="${PIPE} | tee $2"
42+
shift 2
43+
fi
44+
if [ "$1" == "-p" ]; then
45+
SECTION_POSTFIX=$2
46+
shift 2
47+
fi
48+
done
49+
cmd=$1
50+
shift
51+
printf "===$cmd===$SECTION_POSTFIX\n"
52+
echo sh -c "$cmd $* $PIPE" >&2
53+
sh -c "$cmd $* $PIPE"
54+
}
55+
56+
OUTPUT_FORMAT="--output-format json-pretty"
57+
58+
command_section "proxmox-backup-manager versions" $OUTPUT_FORMAT
59+
TMP_DATASTORES=$( mktemp -p /tmp/ )
60+
command_section -t $TMP_DATASTORES "proxmox-backup-manager datastore list" $OUTPUT_FORMAT
61+
62+
command_section "proxmox-backup-manager task list" $OUTPUT_FORMAT
63+
64+
TMP_UPIDS=$( mktemp -p /tmp/ )
65+
66+
TMP_GC_FILES=$( mktemp -p /tmp/ )
67+
jq -r '.[].name' $TMP_DATASTORES | while read -r name; do
68+
TMP_GC=$( mktemp -p /tmp/ )
69+
printf "$TMP_GC\n" >> "$TMP_GC_FILES"
70+
command_section -t "$TMP_GC" -p "$name" "proxmox-backup-manager garbage-collection status" $name $OUTPUT_FORMAT
71+
command_section -p "$name" "proxmox-backup-client status" --repository "localhost:$name" $OUTPUT_FORMAT
72+
jq -r '.upid' "$TMP_GC" >> $TMP_UPIDS
73+
done
74+
75+
cat $TMP_UPIDS | while read -r upid; do
76+
command_section -P "sed -n '/^Removed garbage: /,\$p'" -p "$upid" "proxmox-backup-manager task log" "$upid"
77+
done
78+
79+
printf "$TMP_GC_FILES" >> $TMP_GC_FILES
80+
81+
rm -vf $TMP_DATASTORE $TMP_UPIDS $(cat $TMP_GC_FILES | xargs) >&2
82+
83+
export PBS_PASSWORD=
84+
85+
echo "===EOD==="
86+
echo "="
87+

info

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{'author': 'Maximilian Hill <mhill@inett.de>',
2+
'description': '',
3+
'download_url': '',
4+
'files': {'agent_based': ['proxmox_bs.py'],
5+
'agents': ['plugins/proxmox_bs'],
6+
'lib': ['check_mk/base/cee/plugins/bakery/proxmox_bs.py',
7+
'python3/cmk/base/cee/plugins/bakery/proxmox_bs.py'],
8+
'web': ['plugins/wato/proxmox_bs.py']},
9+
'name': 'proxmox_bs',
10+
'num_files': 5,
11+
'title': 'Proxmox Backup Server',
12+
'version': '0.1.18',
13+
'version.min_required': '2.0.0',
14+
'version.packaged': '2.0.0p3',
15+
'version.usable_until': None}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env python3
2+
# -*- encoding: utf-8; py-indent-offset: 4 -*-
3+
import pprint
4+
from pathlib import Path
5+
from typing import Any, Dict
6+
7+
from .bakery_api.v1 import FileGenerator, OS, Plugin, register
8+
9+
10+
def get_proxmox_bs_files(conf: Dict[str, Any]) -> FileGenerator:
11+
if conf == 'server':
12+
yield Plugin(base_os=OS.LINUX, source=Path("proxmox_bs"))
13+
elif conf == 'client':
14+
yield Plugin(base_os=OS.LINUX, source=Path("proxmox_bs_client"))
15+
16+
17+
register.bakery_plugin(
18+
name="proxmox_bs",
19+
files_function=get_proxmox_bs_files,
20+
)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env python3
2+
# -*- encoding: utf-8; py-indent-offset: 4 -*-
3+
import pprint
4+
from pathlib import Path
5+
from typing import Any, Dict
6+
7+
from .bakery_api.v1 import FileGenerator, OS, Plugin, register
8+
9+
10+
def get_proxmox_bs_files(conf: Dict[str, Any]) -> FileGenerator:
11+
if conf == 'server':
12+
yield Plugin(base_os=OS.LINUX, source=Path("proxmox_bs"))
13+
elif conf == 'client':
14+
yield Plugin(base_os=OS.LINUX, source=Path("proxmox_bs_client"))
15+
16+
17+
register.bakery_plugin(
18+
name="proxmox_bs",
19+
files_function=get_proxmox_bs_files,
20+
)

web/plugins/wato/proxmox_bs.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env python3
2+
# -*- encoding: utf-8; py-indent-offset: 4 -*-
3+
4+
# Copyright (c) 2021 inett GmbH
5+
# Maximilian Hill <mhill@inett.de>
6+
# License: GNU General Public License v2
7+
# A file is subject to the terms and conditions defined in the file COPYING,
8+
# which is part of this source code package.
9+
10+
from cmk.gui.i18n import _
11+
from cmk.gui.plugins.wato import (
12+
HostRulespec,
13+
rulespec_registry,
14+
)
15+
from cmk.gui.cee.plugins.wato.agent_bakery.rulespecs.utils import (
16+
RulespecGroupMonitoringAgentsAgentPlugins
17+
)
18+
from cmk.gui.valuespec import (
19+
DropdownChoice,
20+
)
21+
22+
23+
def _valuespec_agent_config_proxmox_bs():
24+
return DropdownChoice(
25+
title = _("Proxmox Backup Server (Linux)"),
26+
help = _("This will deploy the agent plugin <tt>proxmox_bs</tt>"),
27+
choices = [
28+
( 'server', _("Deploy plugin for Proxmox Backup Server") ),
29+
( 'client', _("Deploy plugin for Proxmox Backup Client only")),
30+
( None, _("Do not deploy plugin for Proxmox Backup") ),
31+
]
32+
)
33+
34+
35+
rulespec_registry.register(
36+
HostRulespec(
37+
group=RulespecGroupMonitoringAgentsAgentPlugins,
38+
name="agent_config:proxmox_bs",
39+
valuespec=_valuespec_agent_config_proxmox_bs,
40+
))

0 commit comments

Comments
 (0)