-
Notifications
You must be signed in to change notification settings - Fork 9
/
first-boot
executable file
·124 lines (116 loc) · 4.81 KB
/
first-boot
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
#!/usr/bin/python
import socket
import logging
import time
import plistlib
import os
import subprocess
import shutil
firstboot_dir = '/usr/local/first-boot'
config_plist = os.path.join(firstboot_dir, 'config.plist')
packages_dir = os.path.join(firstboot_dir, 'packages')
installer = '/usr/sbin/installer'
logfile = '/var/log/first-boot.log'
# Logging Config
log = logging.getLogger('first-boot')
log.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(message)s')
handler_stream = logging.StreamHandler()
handler_stream.setFormatter(formatter)
handler_stream.setLevel(logging.ERROR)
log.addHandler(handler_stream)
handler_file = logging.FileHandler(logfile)
handler_file.setFormatter(formatter)
log.addHandler(handler_file)
def ip_addresses():
command = "ifconfig | grep -E 'inet.[0-9]' | grep -v '127.0.0.1' | awk '{ print $2}' | wc -l"
proc = subprocess.Popen(command, shell=True,stdout=subprocess.PIPE)
return proc.communicate()[0].replace('\n', '')
def all_done():
if not os.listdir(packages_dir):
plist_opts = plistlib.readPlist(config_plist)
sleep_time=10
time.sleep(sleep_time)
cleanup()
if plist_opts.get('NoReboot') == False:
subprocess.call(['/sbin/reboot'])
if plist_opts.get('NoShutdown') == False:
subprocess.call(['/sbin/shutdown', '-h', 'now'])
def cleanup():
log_path = open(logfile, 'a')
log.info('No more packages have been found to install, cleaning up.')
# remove launchdaemon
plist_opts = plistlib.readPlist(config_plist)
launchd = os.path.join('/Library/LaunchDaemons/', plist_opts.get('LaunchDaemon'))
os.remove(launchd)
# remove launchagents
os.remove('/Library/LaunchAgents/se.gu.it.LoginLog.plist')
os.remove('/Library/LaunchAgents/se.gu.it.LoginLog.user.plist')
# remove loginlog.app
shutil.rmtree('/Library/PrivilegedHelperTools/LoginLog.app')
# remove firstboot_dir
shutil.rmtree(firstboot_dir)
# Kill LoginLog
subprocess.call(['/usr/bin/pkill', 'LoginLog'])
def main():
log.info(('''
######################################################
First Boot Package Installer %s
######################################################
''') % time.strftime("%Y-%m-%d %H:%M:%S"))
plist_opts = plistlib.readPlist(config_plist)
# Detect new network hardware
subprocess.call(['/usr/sbin/networksetup', '-detectnewhardware'])
if plist_opts.get('Network') == True:
# Check if the network is up
while True:
print ip_addresses()
if ip_addresses().strip() != "0":
log.info('Network connection is active. ')
break
else:
log.info('Network connection is inactive, retrying...')
time_limit = time.sleep(plist_opts.get('SleepCount'))
retry_limit = plist_opts.get('RetryCount')
# if the packages dir isn't empty, loop over them
if os.listdir(packages_dir):
# We're installing, wait to see the output
sleep_time = 20
for package in os.listdir(packages_dir):
log.info(('Installing %s...') % package)
package_path = os.path.join(packages_dir, package)
command = [installer, '-pkg', package_path, '-target', '/']
# check if we've reached the retry limit
retry_key = package + '_count'
retry_count = plist_opts.get(retry_key, 0)
if retry_count <= retry_limit:
log_path = open(logfile, 'a') # so that data written to it will be appended
task = subprocess.Popen(command, stdout=log_path, stderr=log_path)
task.communicate()
if task.returncode == 0:
# Package installed ok, we're good to remove it
log.info(('%s installed successfully.') % package)
try:
os.remove(package_path)
except:
shutil.rmtree(package_path)
else:
log.info(('%s didn\'t install successfully. Will retry on next boot.') % package)
retry_count = retry_count + 1
plist_opts[retry_key] = retry_count
plistlib.writePlist(plist_opts, os.path.join(firstboot_dir, 'config.plist'))
else:
log.info(('Error limit for %s has been reached, removing the package.') % package)
try:
os.remove(package_path)
except:
shutil.rmtree(package_path)
all_done()
# We're done, reboot if requested. Wait 20 seconds so the log window can be read.
sleep_time = 20
time.sleep(sleep_time)
all_done()
if plist_opts.get('NoReboot') == False:
subprocess.call(['/sbin/reboot'])
if __name__ == '__main__':
main()