Compare commits
61
Commits
0bcb0af57e
..
v1.01
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4514b880d | ||
|
|
e092924c08 | ||
|
|
e7f0e04b1d | ||
|
|
9a61e543c7 | ||
|
|
0ee51eda60 | ||
|
|
95a672af4f | ||
|
|
b609f62b14 | ||
|
|
9967235640 | ||
|
|
095c657d63 | ||
|
|
2d49b17a72 | ||
|
|
96cc58fe7f | ||
|
|
df748e5990 | ||
|
|
a4eb09e4a7 | ||
|
|
e1b3c2a4fc | ||
|
|
8e3d004434 | ||
|
|
acf1c6a892 | ||
|
|
fce7f8b28b | ||
|
|
8fbb9de3a4 | ||
|
|
33ba079ae4 | ||
|
|
f20a5828ec | ||
|
|
46c0e3b542 | ||
|
|
1ecce8636c | ||
|
|
d68d760b5e | ||
|
|
b3f4edea5b | ||
|
|
26282d2c3d | ||
|
|
548541e4d3 | ||
|
|
1835ad3188 | ||
|
|
52500d23ed | ||
|
|
4c9df6c6a4 | ||
|
|
3d7b977f50 | ||
|
|
f45ce65c74 | ||
|
|
3fa7cec025 | ||
|
|
1d97160776 | ||
|
|
6dfa8ac2e4 | ||
|
|
f87f90bfa9 | ||
|
|
8cc63244de | ||
|
|
cb7ef4667c | ||
|
|
e15e4db16d | ||
|
|
372827821a | ||
|
|
43d6546e2a | ||
|
|
7c5911ffa8 | ||
|
|
38bf7e204e | ||
|
|
7a4ed46cb5 | ||
|
|
1a9d3ce1e4 | ||
|
|
e481ed08d8 | ||
|
|
0fbd021569 | ||
|
|
4aef7e6f7c | ||
|
|
68ee0ed6f6 | ||
|
|
cced3d91f3 | ||
|
|
e81dfe21cf | ||
|
|
f1834a91d8 | ||
|
|
41e65eb778 | ||
|
|
fd975299ac | ||
|
|
55308c534f | ||
|
|
f28d0fe221 | ||
|
|
c0262fd84a | ||
|
|
391fa66490 | ||
|
|
ef254ecb12 | ||
|
|
6e80f9fba2 | ||
|
|
8e22979c39 | ||
|
|
17d3e3bf7b |
@@ -160,3 +160,5 @@ cython_debug/
|
|||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.idea/
|
||||||
|
|
||||||
|
/mnt/
|
||||||
|
/img
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: git.zunet.ru/iu/nuitka:v215
|
||||||
|
commands:
|
||||||
|
- nuitka3 src/main.py -o baloon
|
||||||
|
- ls -lh
|
||||||
|
- file baloon
|
||||||
|
|
||||||
|
- name: release
|
||||||
|
# image: woodpeckerci/plugin-gitea-release
|
||||||
|
image: plugins/gitea-release
|
||||||
|
settings:
|
||||||
|
base_url: https://git.zunet.ru
|
||||||
|
files:
|
||||||
|
- "baloon"
|
||||||
|
api_key:
|
||||||
|
from_secret: SEC1
|
||||||
|
target: main
|
||||||
|
title: Ti ${CI_COMMIT_TAG##v}
|
||||||
|
|
||||||
|
when:
|
||||||
|
- event: tag
|
||||||
|
ref: refs/tags/v*
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
FROM python:3
|
||||||
|
|
||||||
|
RUN pip install -U nuitka
|
||||||
+80
-15
@@ -2,33 +2,98 @@
|
|||||||
import os
|
import os
|
||||||
from shutil import disk_usage
|
from shutil import disk_usage
|
||||||
import time
|
import time
|
||||||
|
import argparse
|
||||||
|
|
||||||
BS = 1024**2
|
BS = 1024**2
|
||||||
|
|
||||||
def set_utilization(du, utilization_percent=0.6, baloon_filename='baloon'):
|
def set_utilization(fs, utilization_percent=0.6, baloon_filename='baloon', hysteresis_percent=0.01, quiet=False):
|
||||||
fs = os.path.realpath(du)
|
fs = os.path.realpath(fs)
|
||||||
du = disk_usage(fs)
|
du = disk_usage(fs)
|
||||||
print(f'total: {int(du.total/ 2**30)}GB, used: {int(du.used/ 2**30)}GB, free: {int(du.free/ 2**30)}GB')
|
if utilization_percent < 0.1 or utilization_percent > 0.9:
|
||||||
to_be_wasted = int((du.total * utilization_percent) - du.used)
|
raise ValueError('utilization_percent must be between 0.1 and 0.9')
|
||||||
print(f'to_be_wasted: {int(to_be_wasted/ 2**30)}GB')
|
if hysteresis_percent < 0 or hysteresis_percent > 0.1:
|
||||||
if to_be_wasted < 0:
|
raise ValueError('hysteresis_percent must be between 0 and 0.1')
|
||||||
|
hysteresis = int(du.total * hysteresis_percent)
|
||||||
|
if hysteresis < BS: hysteresis = BS
|
||||||
|
to_be_wasted = int(((du.used+du.free) * utilization_percent) - ((du.used+du.free) - du.free))
|
||||||
|
baloon_filename = os.path.join(fs, baloon_filename)
|
||||||
|
if not quiet:
|
||||||
|
print(f'hysteresis: {hysteresis}bytes')
|
||||||
|
print(f'total: {round(du.total/ 2**30, 3)}GB, used: {round(du.used/ 2**30, 3)}GB, free: {round(du.free/ 2**30, 3)}GB usage: {round(du.used * 100 / (du.used+du.free), 3)}%')
|
||||||
|
print(f'to_be_wasted: {round(to_be_wasted/ 2**30, 3)}GB ')
|
||||||
|
if to_be_wasted < -hysteresis:
|
||||||
to_be_trimmed = abs(to_be_wasted)
|
to_be_trimmed = abs(to_be_wasted)
|
||||||
baloon_size = os.path.getsize(os.path.join(fs, baloon_filename))
|
baloon_size = os.path.getsize(baloon_filename)
|
||||||
if baloon_size > to_be_trimmed:
|
if baloon_size > to_be_trimmed:
|
||||||
os.truncate(os.path.join(fs, baloon_filename), baloon_size - to_be_trimmed)
|
os.truncate(baloon_filename, baloon_size - to_be_trimmed)
|
||||||
else: print(f'can\'t trim {baloon_size} > {to_be_trimmed}')
|
if not quiet: print(f'trimmed {to_be_trimmed} Bytes')
|
||||||
elif to_be_wasted > 0:
|
else:
|
||||||
with open(os.path.join(fs, baloon_filename) , 'ab') as f:
|
if os.path.exists(baloon_filename):
|
||||||
|
os.remove(baloon_filename)
|
||||||
|
if not quiet and to_be_trimmed > baloon_size: print(f'can\'t trim {to_be_trimmed - baloon_size} Bytes')
|
||||||
|
elif to_be_wasted > hysteresis:
|
||||||
|
with open(baloon_filename , 'ab') as f:
|
||||||
last = 0
|
last = 0
|
||||||
|
writed = to_be_wasted
|
||||||
while to_be_wasted > 0:
|
while to_be_wasted > 0:
|
||||||
if time.time() - last > 1:
|
if time.time() - last > 1:
|
||||||
print('\r', end='')
|
if not quiet: print(f'left {int(to_be_wasted/ 2**30)}GB \r', end='')
|
||||||
print(f'left {int(to_be_wasted/ 2**30)}GB ', end='')
|
|
||||||
last = time.time()
|
last = time.time()
|
||||||
write_size = min(to_be_wasted, BS)
|
write_size = min(to_be_wasted, BS)
|
||||||
f.write(b'x' * write_size)
|
f.write(b'x' * write_size)
|
||||||
to_be_wasted -= write_size
|
to_be_wasted -= write_size
|
||||||
print('Done ')
|
if not quiet: print(f'Done, added {writed} bytes')
|
||||||
|
if not quiet:
|
||||||
|
du = disk_usage(fs)
|
||||||
|
print(f'total: {round(du.total/ 2**30, 3)}GB, used: {round(du.used/ 2**30, 3)}GB, free: {round(du.free/ 2**30, 3)}GB usage: {round(du.used * 100 / (du.used+du.free), 3)}%')
|
||||||
|
|
||||||
|
def hysteresis_type(arg):
|
||||||
|
MAX_VAL = 10
|
||||||
|
MIN_VAL = 0
|
||||||
|
try:
|
||||||
|
f = float(arg)
|
||||||
|
except ValueError:
|
||||||
|
raise argparse.ArgumentTypeError("Must be a floating point number")
|
||||||
|
if f < MIN_VAL or f > MAX_VAL:
|
||||||
|
raise argparse.ArgumentTypeError("Argument must be < " + str(MAX_VAL) + " and > " + str(MIN_VAL))
|
||||||
|
return f
|
||||||
|
|
||||||
set_utilization('.')
|
parser = argparse.ArgumentParser(description='Baloon utilize your disk space')
|
||||||
|
parser.add_argument('-v', '--version', action='version', version='%(prog)s 1.0')
|
||||||
|
parser.add_argument('-u', '--utilization', type=int, metavar="[10-90]", choices=range(10, 91), help='percentage of utilization', default=60)
|
||||||
|
parser.add_argument('-b', '--baloon', type=str, metavar="baloon", help='name of the baloon file', default='baloon')
|
||||||
|
parser.add_argument('-s', '--hysteresis', type=hysteresis_type, metavar="[0-10]", help='hysteresis, in percentage of disk size', default=1)
|
||||||
|
parser.add_argument('-f', '--fs', type=str, action='append', metavar="fs", help='path to the filesystem', required=True)
|
||||||
|
parser.add_argument('-d', '--daemon', action='store_true', help='daemon mode')
|
||||||
|
parser.add_argument('-i', '--interval', type=int, help='interval in seconds to work in daemon mode', default=60*60)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
fss = []
|
||||||
|
baloon_filename = args.baloon
|
||||||
|
hysteresis_percent = args.hysteresis/100.0
|
||||||
|
utilization_percent = args.utilization/100.0
|
||||||
|
daemon_mode = args.daemon
|
||||||
|
daemon_mode_interval = args.interval
|
||||||
|
|
||||||
|
for fs in args.fs:
|
||||||
|
fs = os.path.realpath(fs)
|
||||||
|
if not os.path.isdir(fs):
|
||||||
|
raise ValueError(f'{fs} is not a directory')
|
||||||
|
fss.append(fs)
|
||||||
|
|
||||||
|
if not daemon_mode:
|
||||||
|
for p in vars(args):
|
||||||
|
print(f'{p}: {getattr(args, p)}')
|
||||||
|
for fs in fss:
|
||||||
|
set_utilization(fs, utilization_percent, baloon_filename, hysteresis_percent)
|
||||||
|
|
||||||
|
else:
|
||||||
|
while True:
|
||||||
|
for fs in fss:
|
||||||
|
if os.path.isdir(fs):
|
||||||
|
try:
|
||||||
|
set_utilization(fs=fs, utilization_percent=utilization_percent, baloon_filename=baloon_filename, hysteresis_percent=hysteresis_percent, quiet=True)
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
time.sleep(daemon_mode_interval)
|
||||||
|
|||||||
Reference in New Issue
Block a user