Improve VSPC policies support.

This commit is contained in:
Marsell Kukuljevic 2026-06-25 13:54:29 +02:00
parent 80c4c33939
commit 15c9b77230
3 changed files with 83 additions and 13 deletions

View File

@ -12,6 +12,9 @@ CRIT = 2
SECONDS_PER_DAY = 24 * 60 * 60
DAILY = "Daily"
WEEKLY = "Weekly"
# GET HTTP with Bearer auth. Returns data structure parsed from JSON.
#
@ -121,7 +124,7 @@ def parse_arguments():
# ],
# ...
# }
def process(mAgents, bAgents, jobs, restores):
def process(mAgents, bAgents, jobs, restores, policies):
mToB = {}
for agent in bAgents:
mToB[agent["managementAgentUid"]] = agent
@ -139,12 +142,12 @@ def process(mAgents, bAgents, jobs, restores):
# for every (backup agent ID, job ID) pair.
bToR = defaultdict(dict)
for r in restores:
bId = r["backupAgentUid"]
jId = r["jobUid"]
bId = r["backupAgentUid"]
jId = r["jobUid"]
most_recent = bToR[bId].get(jId)
if not most_recent or most_recent["creationDate"] < r["creationDate"]:
bToR[bId][jId] = r
most_recent = bToR[bId].get(jId)
if not most_recent or most_recent["creationDate"] < r["creationDate"]:
bToR[bId][jId] = r
results = defaultdict(list)
for mAgent in mAgents:
@ -194,6 +197,7 @@ def process(mAgents, bAgents, jobs, restores):
jobId = job["instanceUid"]
last = job["lastEndTime"]
sched = job["scheduleType"]
polId = job["backupPolicyUid"]
daysSinceLastRun = None
if last:
@ -222,12 +226,24 @@ def process(mAgents, bAgents, jobs, restores):
warnDays = 0
critDays = 0
if sched == "Daily":
# We use 1.2 & 2.2 here to give wiggle room for jobs to complete if
# they take longer than expected.
warnDays = 1.2
critDays = 2.2
elif sched == "Weekly":
if sched == DAILY:
policyType = policies.get(polId)
if policyType == WEEKLY:
# It may seem silly to check for WEEKLY under a DAILY section,
# but the scheduling allows for this, and we actually use this
# in prod due to backups being performed on a specific day in
# the week.
#
# We use 7.2 & 8.2 here to give wiggle room for jobs to
# complete if they take longer than expected.
warnDays = 7.2
critDays = 8.2
else:
# We use 1.2 & 2.2 here to give wiggle room for jobs to
# complete if they take longer than expected.
warnDays = 1.2
critDays = 2.2
elif sched == WEEKLY:
# Ditto, but for a week
warnDays = 7.2
critDays = 8.2
@ -288,6 +304,54 @@ def process(mAgents, bAgents, jobs, restores):
return results
# Alas, although VSPC's job data does specify whether a job runs "daily", it
# does not tell you which days. Veeam allows "daily" jobs to be configured to
# run on specific days of the week, which is something we use in production to
# run certain backup jobs only on a Saturday.
#
# So we need to filter through VSPC's somewhat inconsistent policy API to find
# daily settings. If a job is supposed to run on exactly one day a week, we
# treat it as weekly, otherwise daily.
#
# NB: if we ever use more than one day during the week (e.g. two), the logic in
# this plugin will need to be changed. The logic here, and in process() above,
# match what we currently do in prod, since a "better" approach will require a
# lot more code for a system we might phase out for something else.
def mergePolicies(linuxPolicies, windowsPolicies, macPolicies):
policies = {}
schedules = {}
for policy in linuxPolicies + macPolicies:
schedule = policy["jobConfiguration"]["scheduleSettings"]
schedules[policy["instanceUid"]] = schedule
for policy in windowsPolicies:
config = policy["jobConfiguration"]
workstationSched = config.get("workstationModeSettings")
serverSched = config.get("serverModeSettings")
schedule = workstationSched or serverSched
if not schedule:
continue
schedule = schedule["scheduleSetting"]
schedule = schedule.get("periodicalScheduleSettings") or schedule
schedules[policy["instanceUid"]] = schedule
for polId, sched in schedules.items():
dailySched = sched.get("dailyScheduleSettings")
if not dailySched:
continue
days = dailySched.get("specificDays")
if days and len(days) == 1:
policies[polId] = WEEKLY
else:
policies[polId] = DAILY
return policies
def print_demo():
print("""
<<<<newveeam>>>>
@ -337,12 +401,18 @@ def main(argv=None):
if args.demo:
return print_demo()
linuxPolicies = get_paginated_json_url(args.hostname, args.port, '/api/v3/configuration/backupPolicies/linux', args.token, args.insecure)
windowsPolicies = get_paginated_json_url(args.hostname, args.port, '/api/v3/configuration/backupPolicies/windows', args.token, args.insecure)
macPolicies = get_paginated_json_url(args.hostname, args.port, '/api/v3/configuration/backupPolicies/mac', args.token, args.insecure)
mAgents = get_paginated_json_url(args.hostname, args.port, '/api/v3/infrastructure/managementAgents', args.token, args.insecure)
bAgents = get_paginated_json_url(args.hostname, args.port, '/api/v3/infrastructure/backupAgents', args.token, args.insecure)
jobs = get_paginated_json_url(args.hostname, args.port, '/api/v3/infrastructure/backupAgents/jobs', args.token, args.insecure)
restores = get_paginated_json_url(args.hostname, args.port, '/api/v3/protectedWorkloads/computersManagedByConsole/restorePoints', args.token, args.insecure)
results = process(mAgents, bAgents, jobs, restores)
policies = mergePolicies(linuxPolicies, windowsPolicies, macPolicies)
results = process(mAgents, bAgents, jobs, restores, policies)
print_out(results)

Binary file not shown.