Commit d652a769 authored by Lisa Casino's avatar Lisa Casino

promise: check size + getDaysUntilFull partition

Adding two functions : getDaysUntilFullPartition and getPartitionSize
thanks to the table "folder" from collector.db
parent 2cdf5261
......@@ -6,6 +6,7 @@ from slapos.grid.promise.generic import GenericPromise
import os
import sys
import pwd
import sqlite3
import argparse
......@@ -22,6 +23,51 @@ class RunPromise(GenericPromise):
# check disk space at least every 3 minutes
self.setPeriodicity(minute=3)
def getPartitionSize(self, user, database, date, day_range):
database = Database(database, create=False, timeout=10)
try:
database.connect()
# if "du" didn't start (or didn't finish), we take the date of yesterday
result_max = database.select(
"folder",
columns = "disk_used*1024, max(datetime(date || ' ' || time))",
where = "datetime(date) >= datetime('%s', '-1 days') AND partition='%s'" % (date, user),
order = "time DESC",
limit = 1).fetchone()
if not result_max or not result_max[0]:
self.logger.info("No result from collector database in partition %s: skipped", user)
return 0
partition_size = result_max[0]
result_min = database.select(
"folder",
columns = "disk_used*1024, min(datetime(date || ' ' || time))",
where = "datetime(date || ' ' || time) >= datetime('%s', '-%s days') and partition='%s'" % (result_max[1], day_range, user),
limit = 1).fetchone()
if not result_min or (result_min == result_max) or not result_min[1]:
return None
timep = '%Y-%m-%d %H:%M:%S'
timespan = datetime.datetime.strptime(result_max[1], timep) - \
datetime.datetime.strptime(result_min[1], timep)
delta_days = timespan.total_seconds() / (3600.*24)
# if we don't have enough information (beginning)
if int(delta_days) <= 3:
self.logger.info("Not enough recent data")
return None
except sqlite3.OperationalError as e:
# if database is still locked after timeout expiration (another process is using it)
# we print warning message and try the promise at next run until max warn count
locked_message = "database is locked"
if locked_message in str(e) and \
not self.raiseOnDatabaseLocked(locked_message):
return None
raise
finally:
try:
database.close()
except Exception:
pass
return partition_size, result_max[1], result_min[0], result_min[1], delta_days
def getDiskSize(self, disk_partition, database):
database = Database(database, create=False, timeout=10)
try:
......@@ -76,6 +122,35 @@ class RunPromise(GenericPromise):
pass
return int(disk_free)
def getDaysUntilFullPartition(self, user, disk_partition, db_path, date, time, day_range):
database = Database(db_path, create=False, timeout=10)
try:
disk_size = self.getDiskSize(disk_partition, db_path)
part_size_now, date_max, part_size_min, date_min, delta_days = self.getPartitionSize(user, db_path, date, day_range)
free_space_min = -((part_size_min - disk_size)/disk_size)
free_space_max = -((part_size_now - disk_size)/disk_size)
change = free_space_min - free_space_max
disk_free_percent = self.getFreeSpace(disk_partition, db_path, date, time)/disk_size
try:
return (disk_free_percent / (change / delta_days), date_min, part_size_min, date_max, part_size_now, delta_days)
except ZeroDivisionError as e:
# no data
return None
except sqlite3.OperationalError as e:
# if database is still locked after timeout expiration (another process is using it)
# we print warning message and try the promise at next run until max warn count
locked_message = "database is locked"
if locked_message in str(e) and \
not self.raiseOnDatabaseLocked(locked_message):
return None
raise
finally:
try:
database.close()
except Exception:
pass
def raiseOnDatabaseLocked(self, locked_message):
max_warn = 10
latest_result_list = self.getLastPromiseResultList(result_count=max_warn)
......@@ -120,6 +195,7 @@ class RunPromise(GenericPromise):
def sense(self):
# find if a disk is mounted on the path
disk_partition = ""
user = pwd.getpwuid(os.getuid()).pw_name
db_path = self.getConfig('collectordb')
check_date = self.getConfig('test-check-date')
path = os.path.join(self.getPartitionFolder(), "") + "extrafolder"
......@@ -161,6 +237,17 @@ class RunPromise(GenericPromise):
free_space = self.getFreeSpace(disk_partition, db_path, currentdate,
currenttime)
days_until_full_tuples = self.getDaysUntilFullPartition(user, disk_partition, db_path, currentdate, currenttime, threshold_days/2)
if days_until_full_tuples is not None:
days_until_full, min_date, min_free, max_date, max_free, day_span = days_until_full_tuples
message = "The partition %s will become full in %.2f days (threshold: %.2f days), checked from %s to %s, %.2f days span" % (
user, days_until_full, threshold_days, min_date, max_date, day_span)
if days_until_full < threshold_days:
self.logger.error(message + ', free space dropped from %.1f%% to %.1f%%: ERROR' % (min_free*100, max_free*100))
else:
self.logger.info(message + ': OK')
if free_space == 0:
return
elif free_space > threshold*1024*1024*1024:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment