Browse code

Move all kickstart code to function ks_install in file isoInstaller.py.

Change-Id: I5cfae1779b77c161e294fa44d873e2da67b6ed31
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/3068
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Divya Thaluru <dthaluru@vmware.com>

xiaolin-vmware authored on 2017/06/27 05:25:16
Showing 13 changed files
1 1
deleted file mode 100644
... ...
@@ -1,58 +0,0 @@
1
-#!/usr/bin/python2
2
-#
3
-#    Copyright (C) 2015 vmware inc.
4
-#
5
-#    Author: Mahmoud Bassiouny <mbassiouny@vmware.com>
6
-
7
-import json
8
-import curses
9
-from sets import Set
10
-from jsonwrapper import JsonWrapper
11
-from menu import Menu
12
-from window import Window
13
-from actionresult import ActionResult
14
-
15
-class CustomPackageSelector(object):
16
-    def __init__(self,  maxy, maxx, install_config):
17
-        self.install_config = install_config
18
-        self.menu_items = []
19
-
20
-        self.maxx = maxx
21
-        self.maxy = maxy
22
-        self.win_width = 60
23
-        self.win_height = 23
24
-
25
-        self.win_starty = (self.maxy - self.win_height) / 2
26
-        self.win_startx = (self.maxx - self.win_width) / 2
27
-
28
-        self.menu_starty = self.win_starty + 3
29
-        self.selected_packages = Set([])
30
-
31
-        self.load_package_list()
32
-
33
-        self.window = Window(self.win_height, self.win_width, self.maxy, self.maxx, 'Select your Packages', True, self.package_menu)
34
-
35
-    def load_package_list(self):
36
-        json_wrapper_package_list = JsonWrapper("packages_full.json");
37
-        package_list_json = json_wrapper_package_list.read()
38
-
39
-        for package in package_list_json["packages"]:
40
-            self.menu_items.append((package, self.exit_function))
41
-        self.package_menu = Menu(self.menu_starty,  self.maxx, self.menu_items, height = 18, selector_menu = True)
42
-
43
-
44
-    def exit_function(self,  selected_indexes):
45
-        json_wrapper_package_list = JsonWrapper("packages_minimal.json");
46
-        package_list_json = json_wrapper_package_list.read()
47
-        selected_items = []
48
-        for index in selected_indexes:
49
-            selected_items.append(self.menu_items[index][0])
50
-
51
-        self.install_config['packages'] = package_list_json["packages"] + selected_items
52
-        return ActionResult(True, None)
53
-
54
-    def display(self, params):
55
-        if (params['custom']):
56
-            return self.window.do_action()
57
-        else:
58
-            return ActionResult(True, None)
59 1
deleted file mode 100755
... ...
@@ -1,51 +0,0 @@
1
-#! /usr/bin/python2
2
-#
3
-#    Copyright (C) 2015 vmware inc.
4
-#
5
-#    Author: Mahmoud Bassiouny <mbassiouny@vmware.com>
6
-
7
-import subprocess
8
-import os
9
-import json
10
-from device import Device
11
-from menu import Menu
12
-from window import Window
13
-from actionresult import ActionResult
14
-
15
-class DiskPartitioner(object):
16
-    def __init__(self,  maxy, maxx):
17
-        self.menu_items = []
18
-
19
-        self.maxx = maxx
20
-        self.maxy = maxy
21
-        self.win_width = 70
22
-        self.win_height = 17
23
-
24
-        self.win_starty = (self.maxy - self.win_height) / 2
25
-        self.win_startx = (self.maxx - self.win_width) / 2
26
-
27
-        self.menu_starty = self.win_starty + 10
28
-
29
-        # initialize the devices
30
-        self.devices = Device.refresh_devices()
31
-
32
-        self.items =   [
33
-                            ('Auto-partitioning - use entire disk',  self.guided_partitions, None),
34
-                            ('Manual - not implemented!',  self.manual_partitions, None),
35
-                        ]
36
-        self.menu = Menu(self.menu_starty,  self.maxx, self.items)
37
-
38
-        self.window = Window(self.win_height, self.win_width, self.maxy, self.maxx, 'Welcome to the Photon installer', True, self.menu)
39
-        self.window.addstr(0, 0, 'First, we will setup your disks. \n\nYou can: \n\na) use auto-partitioning or\nb) you can do it manually.')
40
-
41
-    def guided_partitions(self, params):
42
-        return ActionResult(True, {'guided': True, 'devices': self.devices})
43
-
44
-    def manual_partitions(self, params):
45
-        raise NameError('Manual partitioning not implemented')
46
-
47
-    def display(self, params):
48
-        return self.window.do_action()
49
-
50
-
51
-
... ...
@@ -1,5 +1,3 @@
1
-#!/usr/bin/python2
2
-#
3 1
 #    Copyright (C) 2015 vmware inc.
4 2
 #
5 3
 #    Author: Mahmoud Bassiouny <mbassiouny@vmware.com>
... ...
@@ -25,10 +23,8 @@ from __builtin__ import isinstance
25 25
 
26 26
 class Installer(object):
27 27
     def __init__(self, install_config, maxy = 0, maxx = 0, iso_installer = False,
28
-                 rpm_path = "../stage/RPMS", log_path = "../stage/LOGS",
29
-                 ks_config = None):
28
+                 rpm_path = "../stage/RPMS", log_path = "../stage/LOGS"):
30 29
         self.install_config = install_config
31
-        self.ks_config = ks_config
32 30
         self.iso_installer = iso_installer
33 31
         self.rpm_path = rpm_path
34 32
         self.log_path = log_path
... ...
@@ -72,7 +68,7 @@ class Installer(object):
72 72
     def exit_gracefully(self, signal, frame):
73 73
         if self.iso_installer:
74 74
             self.progress_bar.hide()
75
-            self.window.addstr(0, 0, 'Opps, Installer got interrupted.\n\nPress any key to get to the bash...')
75
+            self.window.addstr(0, 0, 'Oops, Installer got interrupted.\n\nPress any key to get to the bash...')
76 76
             self.window.content_window().getch()
77 77
 
78 78
         modules.commons.dump(modules.commons.LOG_FILE_NAME)
... ...
@@ -236,7 +232,7 @@ class Installer(object):
236 236
             self.progress_bar.hide()
237 237
             self.window.addstr(0, 0, 'Congratulations, Photon has been installed in {0} secs.\n\nPress any key to continue to boot...'.format(self.progress_bar.time_elapsed))
238 238
             eject_cdrom = True
239
-            if self.ks_config == None:
239
+            if 'ui_install' in self.install_config:
240 240
                 self.window.content_window().getch()
241 241
             if 'eject_cdrom' in self.install_config and not self.install_config['eject_cdrom']:
242 242
                 eject_cdrom = False
... ...
@@ -428,7 +424,7 @@ class Installer(object):
428 428
             if not hasattr(mod, 'execute'):
429 429
                 modules.commons.log(modules.commons.LOG_ERROR, "Error: not able to execute module {}".format(module))
430 430
                 continue
431
-            mod.execute(module, self.ks_config, self.install_config, self.photon_root)
431
+            mod.execute(module, self.install_config, self.photon_root)
432 432
 
433 433
     def adjust_packages_for_vmware_virt(self):
434 434
         try:
... ...
@@ -9,11 +9,13 @@ from ostreeinstaller import OstreeInstaller
9 9
 from ostreeserverinstaller import OstreeServerInstaller
10 10
 
11 11
 class InstallerContainer(object):
12
-    def __init__(self, install_config, maxy = 0, maxx = 0, iso_installer = False, rpm_path = "../stage/RPMS", log_path = "../stage/LOGS", ks_config = None):
12
+    def __init__(self, install_config, maxy = 0, maxx = 0,
13
+        iso_installer = False, rpm_path = "../stage/RPMS",
14
+        log_path = "../stage/LOGS"):
15
+
13 16
         self.install_config = install_config
14 17
         self.maxy = maxy
15 18
         self.maxx = maxx
16
-        self.ks_config = ks_config
17 19
         self.iso_installer = iso_installer
18 20
         self.rpm_path = rpm_path
19 21
         self.log_path = log_path
... ...
@@ -21,10 +23,10 @@ class InstallerContainer(object):
21 21
     def install(self, params):
22 22
         installer = None
23 23
         if self.install_config['type'] == "ostree_host":
24
-            installer = OstreeInstaller(self.install_config, self.maxy, self.maxx, self.iso_installer, self.rpm_path, self.log_path, self.ks_config)
24
+            installer = OstreeInstaller(self.install_config, self.maxy, self.maxx, self.iso_installer, self.rpm_path, self.log_path)
25 25
         elif self.install_config['type'] == "ostree_server":
26
-            installer = OstreeServerInstaller(self.install_config, self.maxy, self.maxx, self.iso_installer, self.rpm_path, self.log_path, self.ks_config)
26
+            installer = OstreeServerInstaller(self.install_config, self.maxy, self.maxx, self.iso_installer, self.rpm_path, self.log_path)
27 27
         else:
28
-            installer = Installer(self.install_config, self.maxy, self.maxx, self.iso_installer, self.rpm_path, self.log_path, self.ks_config)
28
+            installer = Installer(self.install_config, self.maxy, self.maxx, self.iso_installer, self.rpm_path, self.log_path)
29 29
 
30 30
         return installer.install(params)
31 31
\ No newline at end of file
... ...
@@ -34,6 +34,7 @@ class IsoInstaller(object):
34 34
         if path.startswith("http://"):
35 35
             # Do 5 trials to get the kick start
36 36
             # TODO: make sure the installer run after network is up
37
+            ks_file_error = "Failed to get the kickstart file at {0}".format(path)
37 38
             wait = 1
38 39
             for x in range(0, 5):
39 40
                 err_msg = ""
... ...
@@ -44,14 +45,19 @@ class IsoInstaller(object):
44 44
                     err_msg = response.text
45 45
                 except Exception as e:
46 46
                     err_msg = e
47
-                modules.commons.log(modules.commons.LOG_ERROR, "Failed to get the kickstart file at {0}, error msg: {1}".format(path, err_msg))
48
-                print "Failed to get the kickstart file at {0}, retry in a second".format(path)
47
+
48
+                modules.commons.log(modules.commons.LOG_ERROR,
49
+                    ks_file_error)
50
+                modules.commons.log(modules.commons.LOG_ERROR,
51
+                    "error msg: {0}".format(err_msg))
52
+                print(ks_file_error)
53
+                print("retry in a second")
49 54
                 time.sleep(wait)
50 55
                 wait = wait * 2
51 56
 
52
-
53 57
             # Something went wrong
54
-            print "Failed to get the kickstart file at {0}, exiting the installer, check the logs for more details".format(path)
58
+            print(ks_file_error)
59
+            print("exiting the installer, check the logs for more details")
55 60
             raise Exception(err_msg)
56 61
         else:
57 62
             if path.startswith("cdrom:/"):
... ...
@@ -75,9 +81,10 @@ class IsoInstaller(object):
75 75
             if retval == 0:
76 76
                 self.cd_path = "/mnt/cdrom"
77 77
                 return
78
-            print "Failed to mount the cd, retry in a second"
78
+            print("Failed to mount the cd, retry in a second")
79 79
             time.sleep(1)
80
-        print "Failed to mount the cd, exiting the installer, check the logs for more details"
80
+        print("Failed to mount the cd, exiting the installer")
81
+        print("check the logs for more details")
81 82
         raise Exception("Can not mount the cd")
82 83
 
83 84
     def validate_hostname(self, hostname):
... ...
@@ -98,14 +105,16 @@ class IsoInstaller(object):
98 98
         machinename = fields[0]
99 99
         return (len(machinename) <= 64) and (ord(machinename[0]) in self.alpha_chars), error_hostname
100 100
 
101
-    def validate_password(self, text):
101
+    @staticmethod
102
+    def validate_password(text):
102 103
         try:
103 104
             p = cracklib.VeryFascistCheck(text)
104 105
         except ValueError, message:
105 106
             p = str(message)
106 107
         return p == text, "Error: " + p
107 108
 
108
-    def generate_password_hash(self, password):
109
+    @staticmethod
110
+    def generate_password_hash(password):
109 111
         shadow_password = crypt.crypt(password, "$6$" + "".join([random.choice(string.ascii_letters + string.digits) for _ in range(16)]))
110 112
         return shadow_password
111 113
 
... ...
@@ -136,6 +145,7 @@ class IsoInstaller(object):
136 136
         random_id = '%12x' % random.randrange(16**12)
137 137
         random_hostname = "photon-" + random_id.strip()
138 138
         install_config = {'iso_system': False}
139
+        install_config['ui_install'] = True
139 140
         license_agreement = License(self.maxy, self.maxx)
140 141
         select_disk = SelectDisk(self.maxy, self.maxx, install_config)
141 142
         select_partition = PartitionISO(self.maxy, self.maxx, install_config)
... ...
@@ -165,7 +175,7 @@ class IsoInstaller(object):
165 165
             None, # confirmation error msg if it's a confirmation text
166 166
             '*', # echo char
167 167
             None, # set of accepted chars
168
-            self.validate_password, # validation function of the input
168
+            IsoInstaller.validate_password, # validation function of the input
169 169
             None,  # post processing of the input field
170 170
             'Set up root password', 'Root password:', 2, install_config)
171 171
         confirm_password_reader = WindowStringReader(
... ...
@@ -175,7 +185,7 @@ class IsoInstaller(object):
175 175
             '*', # echo char
176 176
             None, # set of accepted chars
177 177
             None, # validation function of the input
178
-            self.generate_password_hash, # post processing of the input field
178
+            IsoInstaller.generate_password_hash, # post processing of the input field
179 179
             'Confirm root password', 'Confirm Root password:', 2, install_config)
180 180
 
181 181
         items.append((license_agreement.display, False))
... ...
@@ -227,6 +237,53 @@ class IsoInstaller(object):
227 227
                     if install_config['type'] == 'ostree_server':
228 228
                         index -= 1
229 229
 
230
+    def ks_install(self, options_file, rpm_path, ks_config):
231
+        install_config = ks_config
232
+        install_config['iso_system'] = False
233
+        if self.is_vmware_virtualization() and 'install_linux_esx' not in install_config:
234
+            install_config['install_linux_esx'] = True
235
+
236
+        json_wrapper_option_list = JsonWrapper("build_install_options_all.json")
237
+        option_list_json = json_wrapper_option_list.read()
238
+        options_sorted = option_list_json.items()
239
+
240
+        base_path = os.path.dirname("build_install_options_all.json")
241
+        package_list = []
242
+
243
+        package_list = PackageSelector.get_packages_to_install(options_sorted, install_config['type'], base_path)
244
+        if 'additional_packages' in install_config:
245
+            package_list.extend(install_config['additional_packages'])
246
+        install_config['packages'] = package_list
247
+
248
+        if 'partitions' in install_config:
249
+            partitions = install_config['partitions']
250
+        else:
251
+            partitions = modules.commons.default_partitions
252
+
253
+        install_config['disk'] = modules.commons.partition_disk(install_config['disk'], partitions)
254
+
255
+        if "hostname" in install_config:
256
+            evalhostname = os.popen('printf ' + install_config["hostname"].strip(" ")).readlines()
257
+            install_config['hostname'] = evalhostname[0]
258
+        if "hostname" not in install_config or install_config['hostname'] == "":
259
+            random_id = '%12x' % random.randrange(16**12)
260
+            install_config['hostname'] = "photon-" + random_id.strip()
261
+
262
+        # crypt the password if needed
263
+        if install_config['password']['crypted']:
264
+            install_config['password'] = install_config['password']['text']
265
+        else:
266
+            install_config['password'] = crypt.crypt(install_config['password']['text'],
267
+                "$6$" + "".join([random.choice(string.ascii_letters + string.digits) for _ in range(16)]))
268
+
269
+        installer = InstallerContainer(
270
+            install_config,
271
+            self.maxy, self.maxx,
272
+            True,
273
+            rpm_path=rpm_path,
274
+            log_path="/var/log")
275
+
276
+        installer.install(None)
230 277
 
231 278
     def is_vmware_virtualization(self):
232 279
         process = subprocess.Popen(['systemd-detect-virt'], stdout=subprocess.PIPE)
... ...
@@ -270,22 +327,10 @@ class IsoInstaller(object):
270 270
             self.mount_RPMS_cd()
271 271
             rpm_path = os.path.join(self.cd_path, "RPMS")
272 272
 
273
-        if not ks_config:
274
-            self.ui_install(options_file, rpm_path)
273
+        if ks_config:
274
+            self.ks_install(options_file, rpm_path, ks_config)
275 275
         else:
276
-            install_config = ks_config
277
-            install_config['iso_system'] = False
278
-            if self.is_vmware_virtualization() and 'install_linux_esx' not in install_config:
279
-                install_config['install_linux_esx'] = True
280
-            installer = InstallerContainer(
281
-                install_config,
282
-                self.maxy, self.maxx,
283
-                True,
284
-                rpm_path=rpm_path,
285
-                log_path="/var/log",
286
-                ks_config=ks_config)
287
-
288
-            installer.install(None)
276
+            self.ui_install(options_file, rpm_path)
289 277
 
290 278
 if __name__ == '__main__':
291 279
     usage = "Usage: %prog [options]"
292 280
deleted file mode 100644
... ...
@@ -1,30 +0,0 @@
1
-import os
2
-import commons
3
-from jsonwrapper import JsonWrapper
4
-
5
-install_phase = commons.PRE_INSTALL
6
-enabled = True
7
-
8
-def get_packages_to_install(options, config_type):
9
-        package_list = []
10
-        install_option = options[config_type]
11
-        for include_type in install_option["include"]:
12
-            package_list = package_list + get_packages_to_install(options, include_type)
13
-        json_wrapper_package_list = JsonWrapper(install_option["file"])
14
-        package_list_json = json_wrapper_package_list.read()
15
-        package_list = package_list + package_list_json["packages"]
16
-
17
-        return package_list
18
-
19
-def execute(name, ks_config, config, root):
20
-
21
-    if ks_config:
22
-
23
-        options = JsonWrapper("build_install_options_all.json").read()
24
-        packages = get_packages_to_install(options, ks_config['type'])
25
-
26
-        if 'additional_packages' in ks_config:
27
-            packages.extend(ks_config['additional_packages'])
28
-
29
-        config['type'] = ks_config['type']
30
-        config["packages"] = packages
31 1
deleted file mode 100644
... ...
@@ -1,15 +0,0 @@
1
-import os
2
-import subprocess
3
-import commons
4
-
5
-install_phase = commons.PRE_INSTALL
6
-enabled = True
7
-
8
-def execute(name, ks_config, config, root):
9
-
10
-    if ks_config:
11
-        if 'partitions' in ks_config:
12
-            partitions = ks_config['partitions']
13
-        else:
14
-            partitions = commons.default_partitions
15
-        config['disk'] = commons.partition_disk(ks_config['disk'], partitions)
... ...
@@ -5,10 +5,7 @@ import commons
5 5
 install_phase = commons.POST_INSTALL
6 6
 enabled = True
7 7
 
8
-def execute(name, ks_config, config, root):
9
-
10
-    if ks_config and 'postinstall' in ks_config:
11
-        config['postinstall'] = ks_config['postinstall']
8
+def execute(name, config, root):
12 9
     if 'postinstall' not in config:
13 10
         return
14 11
     # run the script in the chroot environment
... ...
@@ -20,5 +17,10 @@ def execute(name, ks_config, config, root):
20 20
         outfile.write("\n".join(script))
21 21
 
22 22
     os.chmod(script_file, 0700);
23
-    process = subprocess.Popen(["./mk-run-chroot.sh", '-w', root, "/etc/tmpfiles.d/postinstall.sh"])
24
-    process.wait()
23
+    with open("/var/log/installer-kickstart.log","w") as logfile:
24
+        process = subprocess.Popen(["./mk-run-chroot.sh", '-w', root, "/etc/tmpfiles.d/postinstall.sh"],
25
+            stdout=logfile,stderr=logfile)
26
+        retval = process.wait()
27
+        if retval==0:
28
+            return True
29
+        return False
... ...
@@ -5,16 +5,7 @@ import random
5 5
 install_phase = commons.POST_INSTALL
6 6
 enabled = True
7 7
 
8
-def execute(name, ks_config, config, root):
9
-
10
-    if ks_config:
11
-        if "hostname" in ks_config:
12
-            evalhostname = os.popen('printf ' + ks_config["hostname"].strip(" ")).readlines()
13
-            config['hostname'] = evalhostname[0]
14
-        if "hostname" not in config or config['hostname'] == "":
15
-            random_id = '%12x' % random.randrange(16**12)
16
-            config['hostname'] = "photon-" + random_id.strip()
17
-
8
+def execute(name, config, root):
18 9
     hostname = config['hostname']
19 10
 
20 11
     hostname_file = os.path.join(root, 'etc/hostname')
... ...
@@ -7,16 +7,7 @@ import string
7 7
 install_phase = commons.POST_INSTALL
8 8
 enabled = True
9 9
 
10
-def execute(name, ks_config, config, root):
11
-
12
-    if ks_config:
13
-        # crypt the password if needed
14
-        if ks_config['password']['crypted']:
15
-            config['password'] = ks_config['password']['text']
16
-        else:
17
-            config['password'] = crypt.crypt(ks_config['password']['text'], 
18
-                "$6$" + "".join([random.choice(string.ascii_letters + string.digits) for _ in range(16)]))
19
-    
10
+def execute(name, config, root):
20 11
     shadow_password = config['password']
21 12
 
22 13
     passwd_filename = os.path.join(root, 'etc/passwd')
... ...
@@ -5,9 +5,7 @@ import commons
5 5
 install_phase = commons.POST_INSTALL
6 6
 enabled = True
7 7
 
8
-def execute(name, ks_config, config, root):
9
-    if ks_config and 'public_key' in ks_config:
10
-        config['public_key'] = ks_config['public_key']
8
+def execute(name, config, root):
11 9
     if 'public_key' not in config:
12 10
         return
13 11
 
... ...
@@ -12,8 +12,8 @@ from actionresult import ActionResult
12 12
 
13 13
 class OstreeInstaller(Installer):
14 14
 
15
-    def __init__(self, install_config, maxy = 0, maxx = 0, iso_installer = False, rpm_path = "../stage/RPMS", log_path = "../stage/LOGS", ks_config = None):
16
-        Installer.__init__(self, install_config, maxy, maxx, iso_installer, rpm_path, log_path, ks_config)
15
+    def __init__(self, install_config, maxy = 0, maxx = 0, iso_installer = False, rpm_path = "../stage/RPMS", log_path = "../stage/LOGS"):
16
+        Installer.__init__(self, install_config, maxy, maxx, iso_installer, rpm_path, log_path)
17 17
         self.repo_config = {}
18 18
         self.repo_read_conf()
19 19
 
... ...
@@ -93,7 +93,7 @@ class OstreeInstaller(Installer):
93 93
         self.window.show_window()
94 94
         self.progress_bar.initialize("Initializing installation...")
95 95
         self.progress_bar.show()
96
-        
96
+
97 97
         self.execute_modules(modules.commons.PRE_INSTALL)
98 98
 
99 99
         disk = self.install_config['disk']['disk']
... ...
@@ -165,7 +165,7 @@ class OstreeInstaller(Installer):
165 165
         self.progress_bar.update_loading_message("Ready to restart")
166 166
         self.progress_bar.hide()
167 167
         self.window.addstr(0, 0, 'Congratulations, Photon RPM-OSTree Host has been installed in {0} secs.\n\nPress any key to continue to boot...'.format(self.progress_bar.time_elapsed))
168
-        if self.ks_config == None:
168
+        if 'ui_install' in self.install_config:
169 169
             self.window.content_window().getch()
170 170
         return ActionResult(True, None)
171 171
 
... ...
@@ -27,8 +27,8 @@ from installer import Installer
27 27
 
28 28
 class OstreeServerInstaller(Installer):
29 29
 
30
-    def __init__(self, install_config, maxy = 0, maxx = 0, iso_installer = False, rpm_path = "../stage/RPMS", log_path = "../stage/LOGS", ks_config = None):
31
-        Installer.__init__(self, install_config, maxy, maxx, iso_installer, rpm_path, log_path, ks_config)
30
+    def __init__(self, install_config, maxy = 0, maxx = 0, iso_installer = False, rpm_path = "../stage/RPMS", log_path = "../stage/LOGS"):
31
+        Installer.__init__(self, install_config, maxy, maxx, iso_installer, rpm_path, log_path)
32 32
 
33 33
     def finalize_system(self):
34 34
         Installer.finalize_system(self)