CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/scripts/salvus_nbd_format.py
Views: 687
1
#!/usr/bin/python
2
###############################################################################
3
#
4
# CoCalc: Collaborative Calculation
5
#
6
# Copyright (C) 2016, Sagemath Inc.
7
#
8
# This program is free software: you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation, either version 3 of the License, or
11
# (at your option) any later version.
12
#
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
17
#
18
# You should have received a copy of the GNU General Public License
19
# along with this program. If not, see <http://www.gnu.org/licenses/>.
20
#
21
###############################################################################
22
"""
23
Put this in visudo and make damned sure only root can edit this script. This only should be in the VM hosts not the actual VM's.
24
25
salvus ALL=(ALL) NOPASSWD: /usr/local/bin/salvus_nbd_format.py *
26
"""
27
28
import os, random, sys
29
from subprocess import Popen, PIPE
30
31
if len(sys.argv) != 3:
32
print "Usage: %s xfs|ext4|btrfs file.img" % sys.argv[0]
33
sys.exit(1)
34
35
format = sys.argv[1]
36
if format not in ['xfs', 'ext4', 'btrfs']:
37
print "format must be xfs or ext4 or btrfs"
38
sys.exit(1)
39
40
image = os.path.abspath(sys.argv[2])
41
42
if not os.path.exists(image):
43
print "image file %s doesn't exist" % image
44
sys.exit(1)
45
46
47
def cmd(s):
48
print s
49
if os.system(s):
50
raise RuntimeError('failed: "%s"' % s)
51
52
53
def cmd2(s):
54
print s
55
if isinstance(s, str):
56
out = Popen(s, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True)
57
else:
58
out = Popen(s, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=False)
59
e = out.wait()
60
x = out.stdout.read() + out.stderr.read()
61
return x, e
62
63
64
max_part = 64
65
66
67
def nbd(n):
68
cmd("modprobe nbd max_part=%s" % max_part)
69
dev = '/dev/nbd%s' % n
70
if cmd2(['qemu-nbd', '-c', dev, image])[1]:
71
raise RuntimeError(out.stdout.read() + out.stderr.read())
72
else:
73
return dev
74
75
76
def fdisk(dev):
77
x, e = cmd2('echo "n\np\n1\n\n\n\nw" | fdisk %s' % dev)
78
if "is already defined" in x.lower():
79
raise ValueError("already partitioned-- refusing to format.")
80
if e:
81
raise RuntimeError(x)
82
83
84
def mkfs(dev):
85
# WARNING: this takes a long time, especially with xfs
86
if format == 'xfs':
87
cmd("mkfs.%s -f %sp1" % (format, dev))
88
else:
89
cmd("mkfs.%s %sp1" % (format, dev))
90
91
92
def nbd_disconnect(dev):
93
cmd("qemu-nbd -d %s" % dev)
94
95
96
dev = None
97
try:
98
for i in range(max_part):
99
# we try until success, since nbd is flakie.
100
try:
101
dev = nbd(i)
102
fdisk(dev)
103
mkfs(dev)
104
break
105
except RuntimeError:
106
pass
107
finally:
108
if dev is not None:
109
nbd_disconnect(dev)
110
111