-
Notifications
You must be signed in to change notification settings - Fork 20
/
isoInstaller.py
executable file
·182 lines (154 loc) · 6.74 KB
/
isoInstaller.py
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
#! /usr/bin/python3
#/*
# * Copyright © 2020 VMware, Inc.
# * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-only
# */
#
#
# Author: Mahmoud Bassiouny <mbassiouny@vmware.com>
import os
import subprocess
import shlex
import requests
import time
import json
from argparse import ArgumentParser
from installer import Installer
from commandutils import CommandUtils
from jsonwrapper import JsonWrapper
class IsoInstaller(object):
def __init__(self, options):
install_config=None
self.media_mount_path = None
photon_media = None
ks_path = options.install_config_file
# Path to RPMS repository: local media or remote URL
# If --repo-path= provided - use it,
# if not provided - use kernel repo= parameter,
# if not provided - use /RPMS path from photon_media,
# exit otherwise.
repo_path = options.repo_path
self.insecure_installation = None
with open('/proc/cmdline', 'r') as f:
kernel_params = shlex.split(f.read().replace('\n', ''))
for arg in kernel_params:
if arg.startswith("ks="):
if not ks_path:
ks_path = arg[len("ks="):]
elif arg.startswith("repo="):
if not repo_path:
repo_path = arg[len("repo="):]
elif arg.startswith("photon.media="):
photon_media = arg[len("photon.media="):]
elif arg.startswith("insecure_installation="):
self.insecure_installation = bool(int(arg[len("insecure_installation="):]))
if photon_media:
self.media_mount_path = self.mount_media(photon_media)
if not repo_path:
if self.media_mount_path:
repo_path = self.media_mount_path + "/RPMS"
else:
print("Please specify RPM repo path.")
return
if ks_path:
install_config = self._load_ks_config(ks_path)
# insecure_installation flag added through commandline overrides that of ks_config
if self.insecure_installation:
if not install_config:
install_config = {}
install_config['insecure_installation'] = self.insecure_installation
if not install_config:
install_config = {}
install_config['photon_release_version'] = options.photon_release_version
if options.ui_config_file:
ui_config = (JsonWrapper(options.ui_config_file)).read()
else:
ui_config={}
ui_config['options_file'] = options.options_file
#initializing eula file path
ui_config['eula_file_path'] = options.eula_file_path
#initializing license display text
ui_config['license_display_title'] = options.license_display_title
# Run installer
installer = Installer(rpm_path=repo_path, log_path="/var/log")
installer.configure(install_config, ui_config)
installer.execute()
def _load_ks_config(self, path):
"""kick start configuration"""
if path.startswith("http://") and not self.insecure_installation:
raise Exception("Refusing to download kick start configuration from non-https URLs. \
\nPass insecure_installation=1 as a parameter when giving http url in ks.")
if path.startswith("https://") or path.startswith("http://"):
# Do 5 trials to get the kick start
# TODO: make sure the installer run after network is up
ks_file_error = "Failed to get the kickstart file at {0}".format(path)
wait = 1
for _ in range(0, 5):
err_msg = ""
try:
if self.insecure_installation:
response = requests.get(path, timeout=3, verify=False)
else:
response = requests.get(path, timeout=3, verify=True)
except Exception as e:
err_msg = e
else:
return json.loads(response.text)
print("error msg: {0} Retry after {1} seconds".format(err_msg, wait))
time.sleep(wait)
wait = wait * 2
# Something went wrong
print(ks_file_error)
raise Exception(err_msg)
else:
if path.startswith("cdrom:/"):
if self.media_mount_path is None:
raise Exception("cannot read ks config from cdrom, no cdrom specified")
path = os.path.join(self.media_mount_path, path.replace("cdrom:/", "", 1))
elif not path.startswith("/"):
path = os.path.join(os.getcwd(), path)
elif len(path.split(':')) == 2:
ks_path_split = path.split(':')
ks_mounted_path = self.mount_media(ks_path_split[0], mount_path='/mnt/ks')
if ks_path_split[1].startswith("/"):
ks_path_split[1] = ks_path_split[1][1:]
path = os.path.join(ks_mounted_path, ks_path_split[1])
else:
raise Exception("Kickstart file provided is not in correct format.")
return (JsonWrapper(path)).read()
def mount_media(self, photon_media, mount_path="/mnt/media"):
"""Mount the external media"""
# Make the mounted directories
os.makedirs(mount_path, exist_ok=True)
# Construct mount cmdline
cmdline = ['mount']
if photon_media.startswith("UUID="):
cmdline.extend(['-U', photon_media[len("UUID="):] ])
elif photon_media.startswith("LABEL="):
cmdline.extend(['-L', photon_media[len("LABEL="):] ])
elif photon_media == "cdrom":
cmdline.append('/dev/cdrom')
else:
#User specified mount path
cmdline.append(photon_media)
cmdline.extend(['-o', 'ro', mount_path])
# Retry mount the CD
for _ in range(0, 3):
process = subprocess.Popen(cmdline)
retval = process.wait()
if retval == 0:
return mount_path
print("Failed to mount the device, retry in a second")
time.sleep(1)
print("Failed to mount the device, exiting the installer")
print("check the logs for more details")
raise Exception("Can not mount the device")
if __name__ == '__main__':
usage = "Usage: %prog [options]"
parser = ArgumentParser(usage)
parser.add_argument("-c", "--config", dest="install_config_file")
parser.add_argument("-u", "--ui-config", dest="ui_config_file")
parser.add_argument("-j", "--json-file", dest="options_file", default="input.json")
parser.add_argument("-r", "--repo-path", dest="repo_path")
options = parser.parse_args()
IsoInstaller(options)