[Working Blog] ONTAP Snapshot Reporting in Python - Part 6 - When Should the Snapshots Have Been Taken?
From A Cron Schedule, How to Work Out Past Triggerings?
From the ONTAP man pages, these are from the parameter descriptions:
Note: If you specify values for both days of the month and days of the week, they are considered independently.
- month
- Valid values are January, February, March, April, May, June, July, August, September, October, November, December, and all
- dayofweek
- Valid values are Sunday, Monday, Tuesday, Thursday, Friday, and Saturday, and all.
- day
- Valid values range from 1 to 31.
- hour
- Valid values range from 0 (midnight) to 23 (11:00 p.m.).
- minute
- Valid values range from 0 to 59.
def getSnapshots(utcdatetime): #,label,mins,hours,days,dayofweek,month):
## Start Time ##
outStr = ""
currYear = utcdatetime.year ;outStr += str(currYear)+"-"
currMonth = utcdatetime.month ;outStr += "{:02d}".format(currMonth)+"-"
currDay = utcdatetime.day ;outStr += "{:02d}".format(currDay)+"("
currWeekday = utcdatetime.weekday();outStr += str(currWeekday)+")-"
currHour = utcdatetime.hour ;outStr += "{:02d}".format(currHour)+"-"
currMin = utcdatetime.minute ;outStr += "{:02d}".format(currMin)
## Test Output ##
print("YYYY-MM-DD(w)-HH-mm")
print(outStr)
The output of getSnapshots(utcDateTime) looks like this:
YYYY-MM-DD(w)-HH-mm
2025-04-21(0)-12-01
I Made a Mistake in Part 5 (dayofweek and month aren't working)
Since we go back in time from time now (utcDateTime), taking snapshots when the schedule dictates, I need to start with - in order - month, dayofweek/day, hours, minutes. I was curious how month and dayofweek are displayed in the Python outputs, are they numbers or strings!?
month and dayofweek is not used that much, but still, we should factor it in. I created some schedules in ONTAP:
cluster::> cron create -cluster cluster -name zMonthTest -month August -day 17 -minute 5
cluster::> cron create -cluster cluster -name zDoWtest -dayofweek Thursday -minute 5
But, August and Thursday did not appear in the Python outputs:
schedNameToUUID['zMonthTest']
'84f40b3a-1f58-11f0-b3b9-005056b7e14b'
schedNameToUUID['zDoWtest']
'9b0430e9-1f58-11f0-b3b9-005056b7e14b'
schedByUUID['84f40b3a-1f58-11f0-b3b9-005056b7e14b']
{'minutes': [5], 'hours': ['X'], 'days': [17], 'dayofweek': ['X'], 'month': ['X']}
schedByUUID['9b0430e9-1f58-11f0-b3b9-005056b7e14b']
{'minutes': [5], 'hours': ['X'], 'days': ['X'], 'dayofweek': ['X'], 'month': ['X']}
How to fix this issue?
Look at the data, the fix is simple, we should be using weekdays and months (not dayofweek and month), and yes, the output is a number (Thursday is a 4, August is an 8).
I have fixed the code in part 5.
Continuing with def getSnapshots
Thinking logically, what it is we want to do?
- Start at time x
- Loop back one minute at a time with exceptions:
- if no months ignore this:
- if month not in months
- set day to 1, hour to 0, minute to 0
- -1 minute
- and repeat until our month is in months
- if no days or weekdays ignore this:
- if day not in days or weekdays
- set hour to 0 and minute to 0
- -1 minute
- and repeat until our days is in days
- if no hours ignore this:
- if hour not in hours
- set minute to 0
- -1 minute
- and repeat until our hour is in hours
- if minute not in minutes
- -1 minute
- else, if everything aligns, record a snapshot
- count++
- Repeat for as many as is the count (number of snapshots) defined by the Snapshot Policy.
And this is what I came up with.
from datetime import datetime, timedelta
def getSnapshots(utcdatetime,prefix,count,minutes,hours,days,weekdays,months):
## Variables ##
xTime = utcdatetime + datetime.timedelta(minutes=1)
go = True
snapCount = 0
snapList = []
## The Go Back In A Minute at a Time Loop ##
while go:
match = False
xTime = xTime - timedelta(minutes=1)
xYear = xTime.year
xMonth = xTime.month
xDay = xTime.day
xWeekDay = xTime.weekday()
xHour = xTime.hour
xMinute = xTime.minute
## Checking months ##
if months != 'X':
if xMonth not in set(months):
xTime = datetime.datetime(xYear,xMonth,1,0,0)
continue
# otherwise we might have a match ...
## Checking day/weekday ##
if days != 'X' and weekdays != 'X':
if xDay not in set(days) or xWeekDay not in set(weekdays):
xTime = datetime.datetime(xYear,xMonth,xDay,0,0)
continue
# otherwise we might have a match ...
## Checking hour ##
if hours != 'X':
if xHour not in set(hours):
xTime = datetime.datetime(xYear,xMonth,xDay,xHour,0)
continue
# otherwise we might have a match ...
## Checking minute ##
if xMinute in set(minutes):
if hours == 'X' and days == 'X' and weekdays == 'X' and months == 'X':
match = True
elif xHour in set(hours):
if days == 'X' and weekdays == 'X' and months == 'X':
match = True
elif xDay in set(days) or xWeekDay in set(weekdays):
if months == 'X':
match = True
elif xMonth in set(months):
match = True
## The snapshot ##
if match:
## Snap Name at time x (PREFIX.YYYY-MM-DD_HHmm) ##
xSnapName = prefix + "."
xSnapName += str(xYear) + "-"
xSnapName += "{:02d}".format(xMonth) + "-"
xSnapName += "{:02d}".format(xDay) + "_"
xSnapName += "{:02d}".format(xHour)
xSnapName += "{:02d}".format(xMin)
snapList += [xSnapName]
snapCount += 1
## Count check ##
if snapCount >= count:
go = False
Other Thoughts
- I'll need to make sure the inputs (minutes, hours, days, weekdays, months) are lists - otherwise we will get syntax errors. I'm pretty sure this is good, we may need to fix in part 7.
- Cron considerations:
- What happens if a schedule just has month and minute?
- Assumption: day = 1
- What happens if a schedule has day/weekday and no hour?
- Assumption: hour = 0
To be continued in part 7...
Comments
Post a Comment