/
lmn-appliance
207 lines (183 loc) · 7.12 KB
/
lmn-appliance
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/env python3
#
# lmn-appliance
# thomas@linuxmuster.net
# 20230105
#
import configparser
import getopt
import os
import subprocess
import sys
import urllib.request
# check for root user and go on
if not os.geteuid() == 0:
sys.exit('Please start the script as root user.\n You can use the command "sudo -i" to achieve this.')
lvmvols_default = 'var:10,linbo:40,global:10,default-school:100%FREE'
# help
def usage(rc):
print('\nInstalls linuxmuster.net package repo, downloads and installs linuxmuster-prepare package.')
print('If profile option is set it initially prepares a linuxmuster.net ubuntu appliance.\n')
print('\nUsage: lmn-appliance [options]')
print('\n[options] are:\n')
print('-t, --hostname=<hostname> : Hostname to apply (optional, works only with')
print(' server profile).')
print('-n, --ipnet=<ip/bitmask> : Ip address and bitmask assigned to the host')
print(' (optional, default is 10.0.0.x/16, depending')
print(' on the profile).')
print('-p, --profile=<profile> : Host profile to apply, mandatory. Expected')
print(' values are "server" or "ubuntu".')
print(' Profile name is also used as hostname, except for')
print(' "server" if set with -t.')
print('-l, --pvdevice=<device> : Initially sets up lvm on the given device (server')
print(' profile only). <device> can be a partition or an')
print(' entire disk.')
print('-v, --volumes=<volumelist> : List of lvm volumes to create (to be used together')
print(' with -l/--pvdevice). Syntax (size in GiB):')
print(' <name>:<size>,<name>:<size>,...')
print('-w, --swapsize=<size> : Swapfile size in GB (default "2").')
print('-f, --firewall=<firewallip> : Firewall/gateway ip (default *.254).')
print('-g, --gateway=<ip> : Gateway ip address (default is firewall ip).')
print('-d, --domain=<domainname> : Domainname (default linuxmuster.lan).')
print('-u, --unattended : Unattended mode, do not ask, use defaults.')
print('-b, --reboot : Reboots finally (only in unattended mode).')
print('-h, --help : Print this help.')
print('\nNote on lvm volumes:')
print('- Default value for volumes is:')
print(' "' + lvmvols_default + '".')
print('- At least "linbo", "global" and "default-school" must be given.')
print('- "nn%FREE" means "use nn% of the remaining free space of the device for this volume".')
print(' Example: "linbo:50%FREE,global:10,default-school:100%FREE" means "linbo" takes 50% of')
print(' the volume, "global" takes 10G and "default-school" finally takes all of the rest.')
print('- "global" and "default-school" are mounted with quota options.')
sys.exit(rc)
# get cli args
try:
opts, args = getopt.getopt(sys.argv[1:], "bd:f:hl:n:p:t:uv:w:", [
"reboot", "domain=", "firewall=", "help", "volumes=", "swapsize=", "pvdevice=", "ipnet=", "profile=", "hostname=", "unattended"])
except getopt.GetoptError as err:
# print help information and exit:
print(err) # will print something like "option -a not recognized"
usage(2)
# default values
unattended = ''
reboot = ''
profile = ''
hostname = ''
domainname = ''
firewallip = ''
gateway = ''
ipnet = ''
volumes = ''
pvdevice = ''
swapsize = ''
profile_list = ['server', 'ubuntu']
# evaluate options
for o, a in opts:
if o in ("-u", "--unattended"):
unattended = ' -u'
if o in ("-b", "--reboot"):
reboot = ' -b'
elif o in ("-p", "--profile"):
profile = a
elif o in ("-t", "--hostname"):
hostname = ' -t ' + a
elif o in ("-v", "--volumes"):
volumes = ' -v ' + a
elif o in ("-v", "--volumes"):
swapsize = ' -w ' + a
elif o in ("-l", "--pvdevice"):
pvdevice = ' -l ' + a
elif o in ("-d", "--domain"):
domainname = ' -d ' + a
elif o in ("-n", "--ipnet"):
ipnet = ' -n ' + a
elif o in ("-f", "--firewall"):
firewallip = ' -f ' + a
elif o in ("-g", "--gateway"):
gateway = ' -g ' + a
elif o in ("-h", "--help"):
usage(0)
else:
assert False, "unhandled option"
usage(1)
if profile != '' and profile not in profile_list:
print('\nUnknown profile: ' + profile + '.')
usage(1)
# repo data
lmnkey_remote = 'https://deb.linuxmuster.net/pub.gpg'
lmnkey_local = '/etc/apt/trusted.gpg.d/linuxmuster.net.gpg'
lmn71_list = '/etc/apt/sources.list.d/lmn71.list'
lmn72_list = '/etc/apt/sources.list.d/lmn72.list'
lmn71_deb = 'deb https://deb.linuxmuster.net/ lmn71 main'
lmn72_deb = 'deb https://deb.linuxmuster.net/ lmn72 main'
pkgname = 'linuxmuster-prepare'
# return content of text file
def readTextfile(tfile):
if not os.path.isfile(tfile):
return False, None
try:
infile = open(tfile, 'r')
content = infile.read()
infile.close()
return True, content
except:
print('Cannot read ' + tfile + '!')
return False, None
# write textfile
def writeTextfile(tfile, content, flag):
try:
outfile = open(tfile, flag)
outfile.write(content)
outfile.close()
return True
except:
print('Failed to write ' + tfile + '!')
return False
# get os release
def os_release():
# read data
rc, content = readTextfile('/etc/os-release')
# insert a section
content = "[OS]\n" + content
content = content.replace('"', '')
# read the os data
os_data = configparser.ConfigParser()
os_data.read_string(content)
return os_data['OS']['ID'], os_data['OS']['VERSION_ID']
# install repos
id, version = os_release()
if id != 'ubuntu':
print(id + ' is not the expected os.')
sys.exit(1)
if version == '18.04':
lmn_version = '7.1'
lmn_list = lmn71_list
lmn_deb = lmn71_deb
elif version == '22.04':
lmn_version = '7.2'
lmn_list = lmn72_list
lmn_deb = lmn72_deb
else:
print(version + ' is not the expected version.')
sys.exit(1)
print('## install lmn ' + lmn_version + ' repo')
urllib.request.urlretrieve(lmnkey_remote, lmnkey_local)
writeTextfile(lmn_list, lmn_deb + '\n', 'w')
# 7.2 needs the 7.1 repo too
if lmn_version == '7.2':
writeTextfile(lmn72_list, lmn71_deb, 'a')
# get updates
print('## install software updates')
subprocess.call('apt clean', shell=True)
subprocess.call('apt update', shell=True)
subprocess.call('DEBIAN_FRONTEND=noninteractive apt -y dist-upgrade', shell=True)
# get lmn72 packages
print('## install ' + pkgname + ' package')
subprocess.call('DEBIAN_FRONTEND=noninteractive echo -e "y\ny\ny\n" | apt -y install ' + pkgname, shell=True)
# invoke prepare script if profile is set
if profile != '':
print('## invoke lmn-prepare')
profile = ' -p ' + profile
subprocess.call('lmn-prepare -i' + unattended + reboot + profile
+ hostname + domainname + firewallip + gateway + ipnet + volumes + pvdevice + swapsize, shell=True)