-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
scylla_swap_setup
executable file
·121 lines (104 loc) · 3.83 KB
/
scylla_swap_setup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright 2019-present ScyllaDB
#
#
# SPDX-License-Identifier: AGPL-3.0-or-later
import os
import sys
import argparse
import psutil
from pathlib import Path
from scylla_util import *
from subprocess import run
def GB(n):
return n * 1024 * 1024 * 1024
def to_GB(n):
return '{:.2f}'.format(n / 1024 / 1024 / 1024)
def find_mount_point(path):
path = path.absolute()
while not path.is_mount():
path = path.parent
return path
def get_fs_type(path):
mnt = find_mount_point(path)
for part in psutil.disk_partitions():
if part.mountpoint == str(mnt):
return part.fstype
return None
if __name__ == '__main__':
if os.getuid() > 0:
print('Requires root permission.')
sys.exit(1)
parser = argparse.ArgumentParser(description='Configure swap for Scylla.')
parser.add_argument('--swap-directory',
help='specify swapfile directory', default='/')
parser.add_argument('--swap-size', type=int,
help='specify swapfile size in GB')
parser.add_argument('--swap-size-bytes', type=int,
help='specify swapfile size in bytes')
args = parser.parse_args()
if swap_exists():
print('swap already configured, exiting setup')
sys.exit(1)
if args.swap_size and args.swap_size_bytes:
print("Cannot specify both --swap-size and --swap-size-bytes")
sys.exit(1)
swap_directory = Path(args.swap_directory)
swapfile = swap_directory / 'swapfile'
if swapfile.exists():
print('swapfile {} already exists'.format(swapfile))
sys.exit(1)
swapunit_bn = out('systemd-escape -p --suffix=swap {}'.format(swapfile))
swapunit = Path('/etc/systemd/system/{}'.format(swapunit_bn))
if swapunit.exists():
print('swap unit {} already exists'.format(swapunit))
sys.exit(1)
diskfree = psutil.disk_usage(args.swap_directory).free
if args.swap_size or args.swap_size_bytes:
if args.swap_size:
swapsize = GB(args.swap_size)
else:
swapsize = args.swap_size_bytes
if swapsize > diskfree:
print('swap directory {} does not have enough disk space. {}GB space required.'.format(args.swap_directory, to_GB(swapsize)))
sys.exit(1)
else:
memtotal = psutil.virtual_memory().total
# Scylla document says 'swap size should be set to either total_mem/3 or
# 16GB - lower of the two', so we need to compare 16g vs memtotal/3 and
# choose lower one
# see: https://docs.scylladb.com/faq/#do-i-need-to-configure-swap-on-a-scylla-node
swapsize = GB(16) if GB(16) < int(memtotal / 3) else int(memtotal / 3)
# We should not fill entire disk space with swapfile, it's safer to limit
# swap size 50% of diskfree
half_of_diskfree = int(diskfree / 2)
if swapsize > half_of_diskfree:
# out of disk space, abort setup
if half_of_diskfree <= GB(1):
print('swap directory {} does not have enough disk space.')
sys.exit(1)
swapsize = half_of_diskfree
swapsize_mb = int(swapsize / 1024 / 1024)
fs_type = get_fs_type(swap_directory)
if fs_type == 'ext4':
run(f'fallocate -l {swapsize_mb}MiB {swapfile}', shell=True, check=True)
else:
run('dd if=/dev/zero of={} bs=1M count={}'.format(swapfile, swapsize_mb), shell=True, check=True)
swapfile.chmod(0o600)
run('mkswap -f {}'.format(swapfile), shell=True, check=True)
unit_data = '''
[Unit]
Description=swapfile
[Swap]
What={}
[Install]
WantedBy=multi-user.target
'''[1:-1].format(swapfile)
with swapunit.open('w') as f:
f.write(unit_data)
systemd_unit.reload()
swap = systemd_unit(swapunit_bn)
swap.enable()
swap.start()