Change-Id: Idad0f5e11a41c048ec8b187e1bf93a5ea29af918
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/4614
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Divya Thaluru <dthaluru@vmware.com>
| ... | ... |
@@ -3,7 +3,6 @@ |
| 3 | 3 |
# Author: Mahmoud Bassiouny <mbassiouny@vmware.com> |
| 4 | 4 |
|
| 5 | 5 |
import subprocess |
| 6 |
-import curses |
|
| 7 | 6 |
import os |
| 8 | 7 |
import shutil |
| 9 | 8 |
import signal |
| ... | ... |
@@ -34,7 +33,7 @@ class Installer(object): |
| 34 | 34 |
else: |
| 35 | 35 |
self.working_directory = "/mnt/photon-root" |
| 36 | 36 |
self.photon_root = self.working_directory + "/photon-chroot" |
| 37 |
- |
|
| 37 |
+ self.rpms_tobeinstalled = None |
|
| 38 | 38 |
self.restart_command = "shutdown" |
| 39 | 39 |
|
| 40 | 40 |
if self.iso_installer: |
| ... | ... |
@@ -62,7 +61,9 @@ class Installer(object): |
| 62 | 62 |
signal.signal(signal.SIGINT, self.exit_gracefully) |
| 63 | 63 |
|
| 64 | 64 |
# This will be called if the installer interrupted by Ctrl+C or exception |
| 65 |
- def exit_gracefully(self, signal, frame): |
|
| 65 |
+ def exit_gracefully(self, signal1, frame1): |
|
| 66 |
+ del signal1 |
|
| 67 |
+ del frame1 |
|
| 66 | 68 |
if self.iso_installer: |
| 67 | 69 |
self.progress_bar.hide() |
| 68 | 70 |
self.window.addstr(0, 0, 'Oops, Installer got interrupted.\n\n' + |
| ... | ... |
@@ -73,8 +74,9 @@ class Installer(object): |
| 73 | 73 |
sys.exit(1) |
| 74 | 74 |
|
| 75 | 75 |
def install(self, params): |
| 76 |
+ del params |
|
| 76 | 77 |
try: |
| 77 |
- return self.unsafe_install(params) |
|
| 78 |
+ return self.unsafe_install() |
|
| 78 | 79 |
except Exception as inst: |
| 79 | 80 |
if self.iso_installer: |
| 80 | 81 |
modules.commons.log(modules.commons.LOG_ERROR, repr(inst)) |
| ... | ... |
@@ -82,105 +84,13 @@ class Installer(object): |
| 82 | 82 |
else: |
| 83 | 83 |
raise |
| 84 | 84 |
|
| 85 |
- def unsafe_install(self, params): |
|
| 86 |
- |
|
| 87 |
- if self.iso_installer: |
|
| 88 |
- self.window.show_window() |
|
| 89 |
- self.progress_bar.initialize('Initializing installation...')
|
|
| 90 |
- self.progress_bar.show() |
|
| 91 |
- #self.rpm_path = "https://dl.bintray.com/vmware/photon_release_1.0_TP2_x86_64" |
|
| 92 |
- if self.rpm_path.startswith("https://") or self.rpm_path.startswith("http://"):
|
|
| 93 |
- cmdoption = 's/baseurl.*/baseurl={}/g'.format(self.rpm_path.replace('/', '\/'))
|
|
| 94 |
- process = subprocess.Popen(['sed', '-i', cmdoption, |
|
| 95 |
- '/etc/yum.repos.d/photon-iso.repo']) |
|
| 96 |
- retval = process.wait() |
|
| 97 |
- if retval != 0: |
|
| 98 |
- modules.commons.log(modules.commons.LOG_INFO, "Failed to reset repo") |
|
| 99 |
- self.exit_gracefully(None, None) |
|
| 100 |
- |
|
| 101 |
- cmdoption = ('s/cachedir=\/var/cachedir={}/g'
|
|
| 102 |
- .format(self.photon_root.replace('/', '\/')))
|
|
| 103 |
- process = subprocess.Popen(['sed', '-i', cmdoption, '/etc/tdnf/tdnf.conf']) |
|
| 104 |
- retval = process.wait() |
|
| 105 |
- if retval != 0: |
|
| 106 |
- modules.commons.log(modules.commons.LOG_INFO, "Failed to reset tdnf cachedir") |
|
| 107 |
- self.exit_gracefully(None, None) |
|
| 85 |
+ def unsafe_install(self): |
|
| 86 |
+ self.setup_install_repo() |
|
| 108 | 87 |
self.execute_modules(modules.commons.PRE_INSTALL) |
| 109 | 88 |
|
| 110 | 89 |
self.initialize_system() |
| 111 |
- |
|
| 112 |
- if self.iso_installer: |
|
| 113 |
- self.adjust_packages_for_vmware_virt() |
|
| 114 |
- selected_packages = self.install_config['packages'] |
|
| 115 |
- state = 0 |
|
| 116 |
- packages_to_install = {}
|
|
| 117 |
- total_size = 0 |
|
| 118 |
- with open(modules.commons.TDNF_CMDLINE_FILE_NAME, "w") as tdnf_cmdline_file: |
|
| 119 |
- tdnf_cmdline_file.write("tdnf install --installroot {0} --nogpgcheck {1}"
|
|
| 120 |
- .format(self.photon_root, " ".join(selected_packages))) |
|
| 121 |
- with open(modules.commons.TDNF_LOG_FILE_NAME, "w") as tdnf_errlog: |
|
| 122 |
- process = subprocess.Popen(['tdnf', 'install'] + selected_packages + |
|
| 123 |
- ['--installroot', self.photon_root, '--nogpgcheck', |
|
| 124 |
- '--assumeyes'], stdout=subprocess.PIPE, |
|
| 125 |
- stderr=tdnf_errlog) |
|
| 126 |
- while True: |
|
| 127 |
- output = process.stdout.readline().decode() |
|
| 128 |
- if output == '': |
|
| 129 |
- retval = process.poll() |
|
| 130 |
- if retval is not None: |
|
| 131 |
- break |
|
| 132 |
- if state == 0: |
|
| 133 |
- if output == 'Installing:\n': |
|
| 134 |
- state = 1 |
|
| 135 |
- elif state == 1: #N A EVR Size(readable) Size(in bytes) |
|
| 136 |
- if output == '\n': |
|
| 137 |
- state = 2 |
|
| 138 |
- self.progress_bar.update_num_items(total_size) |
|
| 139 |
- else: |
|
| 140 |
- info = output.split() |
|
| 141 |
- package = '{0}-{1}.{2}'.format(info[0], info[2], info[1])
|
|
| 142 |
- packages_to_install[package] = int(info[5]) |
|
| 143 |
- total_size += int(info[5]) |
|
| 144 |
- elif state == 2: |
|
| 145 |
- if output == 'Downloading:\n': |
|
| 146 |
- self.progress_bar.update_message('Preparing ...')
|
|
| 147 |
- state = 3 |
|
| 148 |
- elif state == 3: |
|
| 149 |
- self.progress_bar.update_message(output) |
|
| 150 |
- if output == 'Running transaction\n': |
|
| 151 |
- state = 4 |
|
| 152 |
- else: |
|
| 153 |
- modules.commons.log(modules.commons.LOG_INFO, "[tdnf] {0}".format(output))
|
|
| 154 |
- prefix = 'Installing/Updating: ' |
|
| 155 |
- if output.startswith(prefix): |
|
| 156 |
- package = output[len(prefix):].rstrip('\n')
|
|
| 157 |
- self.progress_bar.increment(packages_to_install[package]) |
|
| 158 |
- |
|
| 159 |
- self.progress_bar.update_message(output) |
|
| 160 |
- # 0 : succeed; 137 : package already installed; 65 : package not found in repo. |
|
| 161 |
- if retval != 0 and retval != 137: |
|
| 162 |
- modules.commons.log(modules.commons.LOG_ERROR, |
|
| 163 |
- "Failed to install some packages, refer to {0}"
|
|
| 164 |
- .format(modules.commons.TDNF_LOG_FILE_NAME)) |
|
| 165 |
- self.exit_gracefully(None, None) |
|
| 166 |
- else: |
|
| 167 |
- #install packages |
|
| 168 |
- rpms = [] |
|
| 169 |
- for rpm in self.rpms_tobeinstalled: |
|
| 170 |
- # We already installed the filesystem in the preparation |
|
| 171 |
- if rpm['package'] == 'filesystem': |
|
| 172 |
- continue |
|
| 173 |
- rpms.append(rpm['filename']) |
|
| 174 |
- return_value = self.install_package(rpms) |
|
| 175 |
- if return_value != 0: |
|
| 176 |
- self.exit_gracefully(None, None) |
|
| 177 |
- |
|
| 178 |
- |
|
| 179 |
- if self.iso_installer: |
|
| 180 |
- self.progress_bar.show_loading('Finalizing installation')
|
|
| 181 |
- |
|
| 182 |
- if os.path.exists("/etc/resolv.conf"):
|
|
| 183 |
- shutil.copy("/etc/resolv.conf", self.photon_root + '/etc/.')
|
|
| 90 |
+ self.install_packages() |
|
| 91 |
+ self.enable_network_in_chroot() |
|
| 184 | 92 |
self.finalize_system() |
| 185 | 93 |
|
| 186 | 94 |
if not self.install_config['iso_system']: |
| ... | ... |
@@ -228,9 +138,7 @@ class Installer(object): |
| 228 | 228 |
retval = process.wait() |
| 229 | 229 |
|
| 230 | 230 |
self.update_fstab() |
| 231 |
- |
|
| 232 |
- if os.path.exists(self.photon_root + '/etc/resolv.conf'): |
|
| 233 |
- os.remove(self.photon_root + '/etc/resolv.conf') |
|
| 231 |
+ self.disable_network_in_chroot() |
|
| 234 | 232 |
|
| 235 | 233 |
command = [self.unmount_disk_command, '-w', self.photon_root] |
| 236 | 234 |
if not self.install_config['iso_system']: |
| ... | ... |
@@ -240,17 +148,10 @@ class Installer(object): |
| 240 | 240 |
|
| 241 | 241 |
if self.iso_installer: |
| 242 | 242 |
self.progress_bar.hide() |
| 243 |
- self.window.addstr(0, 0, 'Congratulations, Photon has been installed in {0} secs.\n\n' +
|
|
| 243 |
+ self.window.addstr(0, 0, 'Congratulations, Photon has been installed in {0} secs.\n\n'
|
|
| 244 | 244 |
'Press any key to continue to boot...' |
| 245 | 245 |
.format(self.progress_bar.time_elapsed)) |
| 246 |
- eject_cdrom = True |
|
| 247 |
- if 'ui_install' in self.install_config: |
|
| 248 |
- self.window.content_window().getch() |
|
| 249 |
- if 'eject_cdrom' in self.install_config and not self.install_config['eject_cdrom']: |
|
| 250 |
- eject_cdrom = False |
|
| 251 |
- if eject_cdrom: |
|
| 252 |
- process = subprocess.Popen(['eject', '-r'], stdout=self.output) |
|
| 253 |
- process.wait() |
|
| 246 |
+ self.eject_cdrom() |
|
| 254 | 247 |
return ActionResult(True, None) |
| 255 | 248 |
|
| 256 | 249 |
def copy_rpms(self): |
| ... | ... |
@@ -263,7 +164,7 @@ class Installer(object): |
| 263 | 263 |
|
| 264 | 264 |
for pkg in selected_packages: |
| 265 | 265 |
if pkg in pkg_to_rpm_map: |
| 266 |
- if not pkg_to_rpm_map[pkg]['rpm'] is None: |
|
| 266 |
+ if pkg_to_rpm_map[pkg]['rpm'] is not None: |
|
| 267 | 267 |
name = pkg_to_rpm_map[pkg]['rpm'] |
| 268 | 268 |
basename = os.path.basename(name) |
| 269 | 269 |
self.rpms_tobeinstalled.append({'filename': basename, 'path': name,
|
| ... | ... |
@@ -421,7 +322,7 @@ class Installer(object): |
| 421 | 421 |
|
| 422 | 422 |
rpms = set(rpm_file_names) |
| 423 | 423 |
rpm_paths = [] |
| 424 |
- for root, dirs, files in os.walk(self.rpm_path): |
|
| 424 |
+ for root, _, files in os.walk(self.rpm_path): |
|
| 425 | 425 |
for f in files: |
| 426 | 426 |
if f in rpms: |
| 427 | 427 |
rpm_paths.append(os.path.join(root, f)) |
| ... | ... |
@@ -457,7 +358,7 @@ class Installer(object): |
| 457 | 457 |
continue |
| 458 | 458 |
|
| 459 | 459 |
# the module default is disabled |
| 460 |
- if not hasattr(mod, 'enabled') or mod.enabled == False: |
|
| 460 |
+ if not hasattr(mod, 'enabled') or mod.enabled is False: |
|
| 461 | 461 |
modules.commons.log(modules.commons.LOG_INFO, |
| 462 | 462 |
"module {} is not enabled".format(module))
|
| 463 | 463 |
continue |
| ... | ... |
@@ -475,7 +376,7 @@ class Installer(object): |
| 475 | 475 |
"Error: not able to execute module {}".format(module))
|
| 476 | 476 |
continue |
| 477 | 477 |
|
| 478 |
- mod.execute(module, self.install_config, self.photon_root) |
|
| 478 |
+ mod.execute(self.install_config, self.photon_root) |
|
| 479 | 479 |
|
| 480 | 480 |
def adjust_packages_for_vmware_virt(self): |
| 481 | 481 |
try: |
| ... | ... |
@@ -492,3 +393,115 @@ class Installer(object): |
| 492 | 492 |
selected_packages.append('linux-esx')
|
| 493 | 493 |
except KeyError: |
| 494 | 494 |
pass |
| 495 |
+ |
|
| 496 |
+ def setup_install_repo(self): |
|
| 497 |
+ if self.iso_installer: |
|
| 498 |
+ self.window.show_window() |
|
| 499 |
+ self.progress_bar.initialize('Initializing installation...')
|
|
| 500 |
+ self.progress_bar.show() |
|
| 501 |
+ #self.rpm_path = "https://dl.bintray.com/vmware/photon_release_1.0_TP2_x86_64" |
|
| 502 |
+ if self.rpm_path.startswith("https://") or self.rpm_path.startswith("http://"):
|
|
| 503 |
+ cmdoption = 's/baseurl.*/baseurl={}/g'.format(self.rpm_path.replace('/', '\/'))
|
|
| 504 |
+ process = subprocess.Popen(['sed', '-i', cmdoption, |
|
| 505 |
+ '/etc/yum.repos.d/photon-iso.repo']) |
|
| 506 |
+ retval = process.wait() |
|
| 507 |
+ if retval != 0: |
|
| 508 |
+ modules.commons.log(modules.commons.LOG_INFO, "Failed to reset repo") |
|
| 509 |
+ self.exit_gracefully(None, None) |
|
| 510 |
+ |
|
| 511 |
+ cmdoption = ('s/cachedir=\/var/cachedir={}/g'
|
|
| 512 |
+ .format(self.photon_root.replace('/', '\/')))
|
|
| 513 |
+ process = subprocess.Popen(['sed', '-i', cmdoption, '/etc/tdnf/tdnf.conf']) |
|
| 514 |
+ retval = process.wait() |
|
| 515 |
+ if retval != 0: |
|
| 516 |
+ modules.commons.log(modules.commons.LOG_INFO, "Failed to reset tdnf cachedir") |
|
| 517 |
+ self.exit_gracefully(None, None) |
|
| 518 |
+ |
|
| 519 |
+ def install_packages(self): |
|
| 520 |
+ if self.iso_installer: |
|
| 521 |
+ self.tdnf_install_packages() |
|
| 522 |
+ else: |
|
| 523 |
+ #install packages |
|
| 524 |
+ rpms = [] |
|
| 525 |
+ for rpm in self.rpms_tobeinstalled: |
|
| 526 |
+ # We already installed the filesystem in the preparation |
|
| 527 |
+ if rpm['package'] == 'filesystem': |
|
| 528 |
+ continue |
|
| 529 |
+ rpms.append(rpm['filename']) |
|
| 530 |
+ return_value = self.install_package(rpms) |
|
| 531 |
+ if return_value != 0: |
|
| 532 |
+ self.exit_gracefully(None, None) |
|
| 533 |
+ |
|
| 534 |
+ def tdnf_install_packages(self): |
|
| 535 |
+ self.adjust_packages_for_vmware_virt() |
|
| 536 |
+ selected_packages = self.install_config['packages'] |
|
| 537 |
+ state = 0 |
|
| 538 |
+ packages_to_install = {}
|
|
| 539 |
+ total_size = 0 |
|
| 540 |
+ with open(modules.commons.TDNF_CMDLINE_FILE_NAME, "w") as tdnf_cmdline_file: |
|
| 541 |
+ tdnf_cmdline_file.write("tdnf install --installroot {0} --nogpgcheck {1}"
|
|
| 542 |
+ .format(self.photon_root, " ".join(selected_packages))) |
|
| 543 |
+ with open(modules.commons.TDNF_LOG_FILE_NAME, "w") as tdnf_errlog: |
|
| 544 |
+ process = subprocess.Popen(['tdnf', 'install'] + selected_packages + |
|
| 545 |
+ ['--installroot', self.photon_root, '--nogpgcheck', |
|
| 546 |
+ '--assumeyes'], stdout=subprocess.PIPE, |
|
| 547 |
+ stderr=tdnf_errlog) |
|
| 548 |
+ while True: |
|
| 549 |
+ output = process.stdout.readline().decode() |
|
| 550 |
+ if output == '': |
|
| 551 |
+ retval = process.poll() |
|
| 552 |
+ if retval is not None: |
|
| 553 |
+ break |
|
| 554 |
+ if state == 0: |
|
| 555 |
+ if output == 'Installing:\n': |
|
| 556 |
+ state = 1 |
|
| 557 |
+ elif state == 1: #N A EVR Size(readable) Size(in bytes) |
|
| 558 |
+ if output == '\n': |
|
| 559 |
+ state = 2 |
|
| 560 |
+ self.progress_bar.update_num_items(total_size) |
|
| 561 |
+ else: |
|
| 562 |
+ info = output.split() |
|
| 563 |
+ package = '{0}-{1}.{2}'.format(info[0], info[2], info[1])
|
|
| 564 |
+ packages_to_install[package] = int(info[5]) |
|
| 565 |
+ total_size += int(info[5]) |
|
| 566 |
+ elif state == 2: |
|
| 567 |
+ if output == 'Downloading:\n': |
|
| 568 |
+ self.progress_bar.update_message('Preparing ...')
|
|
| 569 |
+ state = 3 |
|
| 570 |
+ elif state == 3: |
|
| 571 |
+ self.progress_bar.update_message(output) |
|
| 572 |
+ if output == 'Running transaction\n': |
|
| 573 |
+ state = 4 |
|
| 574 |
+ else: |
|
| 575 |
+ modules.commons.log(modules.commons.LOG_INFO, "[tdnf] {0}".format(output))
|
|
| 576 |
+ prefix = 'Installing/Updating: ' |
|
| 577 |
+ if output.startswith(prefix): |
|
| 578 |
+ package = output[len(prefix):].rstrip('\n')
|
|
| 579 |
+ self.progress_bar.increment(packages_to_install[package]) |
|
| 580 |
+ |
|
| 581 |
+ self.progress_bar.update_message(output) |
|
| 582 |
+ # 0 : succeed; 137 : package already installed; 65 : package not found in repo. |
|
| 583 |
+ if retval != 0 and retval != 137: |
|
| 584 |
+ modules.commons.log(modules.commons.LOG_ERROR, |
|
| 585 |
+ "Failed to install some packages, refer to {0}"
|
|
| 586 |
+ .format(modules.commons.TDNF_LOG_FILE_NAME)) |
|
| 587 |
+ self.exit_gracefully(None, None) |
|
| 588 |
+ self.progress_bar.show_loading('Finalizing installation')
|
|
| 589 |
+ |
|
| 590 |
+ def eject_cdrom(self): |
|
| 591 |
+ eject_cdrom = True |
|
| 592 |
+ if 'ui_install' in self.install_config: |
|
| 593 |
+ self.window.content_window().getch() |
|
| 594 |
+ if 'eject_cdrom' in self.install_config and not self.install_config['eject_cdrom']: |
|
| 595 |
+ eject_cdrom = False |
|
| 596 |
+ if eject_cdrom: |
|
| 597 |
+ process = subprocess.Popen(['eject', '-r'], stdout=self.output) |
|
| 598 |
+ process.wait() |
|
| 599 |
+ |
|
| 600 |
+ def enable_network_in_chroot(self): |
|
| 601 |
+ if os.path.exists("/etc/resolv.conf"):
|
|
| 602 |
+ shutil.copy("/etc/resolv.conf", self.photon_root + '/etc/.')
|
|
| 603 |
+ |
|
| 604 |
+ def disable_network_in_chroot(self): |
|
| 605 |
+ if os.path.exists(self.photon_root + '/etc/resolv.conf'): |
|
| 606 |
+ os.remove(self.photon_root + '/etc/resolv.conf') |
| ... | ... |
@@ -18,24 +18,35 @@ from license import License |
| 18 | 18 |
from linuxselector import LinuxSelector |
| 19 | 19 |
|
| 20 | 20 |
class IsoConfig(object): |
| 21 |
- def Configure(self,options_file, maxy, maxx): |
|
| 21 |
+ """This class handles iso installer configuration.""" |
|
| 22 |
+ def __init__(self): |
|
| 22 | 23 |
self.cd_path = None |
| 24 |
+ self.alpha_chars = list(range(65, 91)) |
|
| 25 |
+ self.alpha_chars.extend(range(97, 123)) |
|
| 26 |
+ self.hostname_accepted_chars = self.alpha_chars |
|
| 27 |
+ # Adding the numeric chars |
|
| 28 |
+ self.hostname_accepted_chars.extend(range(48, 58)) |
|
| 29 |
+ # Adding the . and - |
|
| 30 |
+ self.hostname_accepted_chars.extend([ord('.'), ord('-')])
|
|
| 31 |
+ self.random_id = '%12x' % random.randrange(16**12) |
|
| 32 |
+ self.random_hostname = "photon-" + self.random_id.strip() |
|
| 23 | 33 |
|
| 34 |
+ def Configure(self, options_file, maxy, maxx): |
|
| 24 | 35 |
kernel_params = subprocess.check_output(['cat', '/proc/cmdline']) |
| 25 | 36 |
|
| 26 | 37 |
# check for the repo param |
| 27 | 38 |
m = re.match(r".*repo=(\S+)\s*.*\s*", kernel_params.decode()) |
| 28 |
- if m != None: |
|
| 39 |
+ if m is not None: |
|
| 29 | 40 |
rpm_path = m.group(1) |
| 30 | 41 |
else: |
| 31 | 42 |
# the rpms should be in the cd |
| 32 |
- self.mount_RPMS_cd() |
|
| 43 |
+ self.mount_cd() |
|
| 33 | 44 |
rpm_path = os.path.join(self.cd_path, "RPMS") |
| 34 | 45 |
|
| 35 | 46 |
# check the kickstart param |
| 36 | 47 |
ks_config = None |
| 37 | 48 |
m = re.match(r".*ks=(\S+)\s*.*\s*", kernel_params.decode()) |
| 38 |
- if m != None: |
|
| 49 |
+ if m is not None: |
|
| 39 | 50 |
ks_config = self.get_config(m.group(1)) |
| 40 | 51 |
|
| 41 | 52 |
install_config = None |
| ... | ... |
@@ -45,21 +56,23 @@ class IsoConfig(object): |
| 45 | 45 |
install_config = self.ui_config(options_file, maxy, maxx) |
| 46 | 46 |
return rpm_path, install_config |
| 47 | 47 |
|
| 48 |
- def is_vmware_virtualization(self): |
|
| 48 |
+ @staticmethod |
|
| 49 |
+ def is_vmware_virtualization(): |
|
| 50 |
+ """Detect vmware vm""" |
|
| 49 | 51 |
process = subprocess.Popen(['systemd-detect-virt'], stdout=subprocess.PIPE) |
| 50 | 52 |
out, err = process.communicate() |
| 51 | 53 |
if err is not None and err != 0: |
| 52 | 54 |
return False |
| 53 |
- else: |
|
| 54 |
- return out == 'vmware\n' |
|
| 55 |
+ return out == 'vmware\n' |
|
| 55 | 56 |
|
| 56 | 57 |
def get_config(self, path): |
| 58 |
+ """kick start configuration""" |
|
| 57 | 59 |
if path.startswith("http://"):
|
| 58 | 60 |
# Do 5 trials to get the kick start |
| 59 | 61 |
# TODO: make sure the installer run after network is up |
| 60 | 62 |
ks_file_error = "Failed to get the kickstart file at {0}".format(path)
|
| 61 | 63 |
wait = 1 |
| 62 |
- for x in range(0, 5): |
|
| 64 |
+ for _ in range(0, 5): |
|
| 63 | 65 |
err_msg = "" |
| 64 | 66 |
try: |
| 65 | 67 |
response = requests.get(path, timeout=3) |
| ... | ... |
@@ -70,9 +83,9 @@ class IsoConfig(object): |
| 70 | 70 |
err_msg = e |
| 71 | 71 |
|
| 72 | 72 |
modules.commons.log(modules.commons.LOG_ERROR, |
| 73 |
- ks_file_error) |
|
| 73 |
+ ks_file_error) |
|
| 74 | 74 |
modules.commons.log(modules.commons.LOG_ERROR, |
| 75 |
- "error msg: {0}".format(err_msg))
|
|
| 75 |
+ "error msg: {0}".format(err_msg))
|
|
| 76 | 76 |
print(ks_file_error) |
| 77 | 77 |
print("retry in a second")
|
| 78 | 78 |
time.sleep(wait) |
| ... | ... |
@@ -84,11 +97,12 @@ class IsoConfig(object): |
| 84 | 84 |
raise Exception(err_msg) |
| 85 | 85 |
else: |
| 86 | 86 |
if path.startswith("cdrom:/"):
|
| 87 |
- self.mount_RPMS_cd() |
|
| 87 |
+ self.mount_cd() |
|
| 88 | 88 |
path = os.path.join(self.cd_path, path.replace("cdrom:/", "", 1))
|
| 89 | 89 |
return (JsonWrapper(path)).read() |
| 90 | 90 |
|
| 91 |
- def mount_RPMS_cd(self): |
|
| 91 |
+ def mount_cd(self): |
|
| 92 |
+ """Mount the cd with RPMS""" |
|
| 92 | 93 |
# check if the cd is already mounted |
| 93 | 94 |
if self.cd_path: |
| 94 | 95 |
return |
| ... | ... |
@@ -98,7 +112,7 @@ class IsoConfig(object): |
| 98 | 98 |
retval = process.wait() |
| 99 | 99 |
|
| 100 | 100 |
# Retry mount the CD |
| 101 |
- for i in range(0, 3): |
|
| 101 |
+ for _ in range(0, 3): |
|
| 102 | 102 |
process = subprocess.Popen(['mount', '/dev/cdrom', '/mnt/cdrom']) |
| 103 | 103 |
retval = process.wait() |
| 104 | 104 |
if retval == 0: |
| ... | ... |
@@ -111,6 +125,8 @@ class IsoConfig(object): |
| 111 | 111 |
raise Exception("Can not mount the cd")
|
| 112 | 112 |
|
| 113 | 113 |
def ks_config(self, options_file, ks_config): |
| 114 |
+ """Load configuration from file""" |
|
| 115 |
+ del options_file |
|
| 114 | 116 |
install_config = ks_config |
| 115 | 117 |
install_config['iso_system'] = False |
| 116 | 118 |
if self.is_vmware_virtualization() and 'install_linux_esx' not in install_config: |
| ... | ... |
@@ -123,7 +139,9 @@ class IsoConfig(object): |
| 123 | 123 |
base_path = os.path.dirname("build_install_options_all.json")
|
| 124 | 124 |
package_list = [] |
| 125 | 125 |
|
| 126 |
- package_list = PackageSelector.get_packages_to_install(options_sorted, install_config['type'], base_path) |
|
| 126 |
+ package_list = PackageSelector.get_packages_to_install(options_sorted, |
|
| 127 |
+ install_config['type'], |
|
| 128 |
+ base_path) |
|
| 127 | 129 |
if 'additional_packages' in install_config: |
| 128 | 130 |
package_list.extend(install_config['additional_packages']) |
| 129 | 131 |
install_config['packages'] = package_list |
| ... | ... |
@@ -139,77 +157,103 @@ class IsoConfig(object): |
| 139 | 139 |
evalhostname = os.popen('printf ' + install_config["hostname"].strip(" ")).readlines()
|
| 140 | 140 |
install_config['hostname'] = evalhostname[0] |
| 141 | 141 |
if "hostname" not in install_config or install_config['hostname'] == "": |
| 142 |
- random_id = '%12x' % random.randrange(16**12) |
|
| 143 |
- install_config['hostname'] = "photon-" + random_id.strip() |
|
| 142 |
+ install_config['hostname'] = "photon-" + self.random_id.strip() |
|
| 144 | 143 |
|
| 145 | 144 |
# crypt the password if needed |
| 146 | 145 |
if install_config['password']['crypted']: |
| 147 | 146 |
install_config['password'] = install_config['password']['text'] |
| 148 | 147 |
else: |
| 149 |
- install_config['password'] = crypt.crypt(install_config['password']['text'], |
|
| 150 |
- "$6$" + "".join([random.choice(string.ascii_letters + string.digits) for _ in range(16)])) |
|
| 148 |
+ install_config['password'] = crypt.crypt( |
|
| 149 |
+ install_config['password']['text'], |
|
| 150 |
+ "$6$" + "".join([random.choice( |
|
| 151 |
+ string.ascii_letters + string.digits) for _ in range(16)])) |
|
| 151 | 152 |
return install_config |
| 152 | 153 |
|
| 153 |
- def validate_hostname(self, hostname): |
|
| 154 |
+ @staticmethod |
|
| 155 |
+ def validate_hostname(hostname): |
|
| 156 |
+ """A valid hostname must start with a letter""" |
|
| 154 | 157 |
error_empty = "Empty hostname or domain is not allowed" |
| 155 | 158 |
error_dash = "Hostname or domain should not start or end with '-'" |
| 156 | 159 |
error_hostname = "Hostname should start with alpha char and <= 64 chars" |
| 157 | 160 |
|
| 158 |
- if hostname is None or len(hostname) == 0: |
|
| 161 |
+ if hostname is None or not hostname: |
|
| 159 | 162 |
return False, error_empty |
| 160 | 163 |
|
| 161 | 164 |
fields = hostname.split('.')
|
| 162 | 165 |
for field in fields: |
| 163 |
- if len(field) == 0: |
|
| 166 |
+ if not field: |
|
| 164 | 167 |
return False, error_empty |
| 165 | 168 |
if field[0] == '-' or field[-1] == '-': |
| 166 | 169 |
return False, error_dash |
| 167 | 170 |
|
| 168 | 171 |
machinename = fields[0] |
| 169 |
- return (len(machinename) <= 64) and (ord(machinename[0]) in self.alpha_chars), error_hostname |
|
| 172 |
+ return (len(machinename) <= 64 and |
|
| 173 |
+ machinename[0].isalpha(), error_hostname) |
|
| 170 | 174 |
|
| 171 | 175 |
@staticmethod |
| 172 | 176 |
def validate_password(text): |
| 177 |
+ """Validate password with cracklib""" |
|
| 173 | 178 |
try: |
| 174 |
- p = cracklib.VeryFascistCheck(text) |
|
| 179 |
+ password = cracklib.VeryFascistCheck(text) |
|
| 175 | 180 |
except ValueError as message: |
| 176 |
- p = str(message) |
|
| 177 |
- return p == text, "Error: " + p |
|
| 181 |
+ password = str(message) |
|
| 182 |
+ return password == text, "Error: " + password |
|
| 178 | 183 |
|
| 179 | 184 |
@staticmethod |
| 180 | 185 |
def generate_password_hash(password): |
| 181 |
- shadow_password = crypt.crypt(password, "$6$" + "".join([random.choice(string.ascii_letters + string.digits) for _ in range(16)])) |
|
| 186 |
+ """Generate hash for the password""" |
|
| 187 |
+ shadow_password = crypt.crypt( |
|
| 188 |
+ password, "$6$" + "".join( |
|
| 189 |
+ [random.choice( |
|
| 190 |
+ string.ascii_letters + string.digits) for _ in range(16)])) |
|
| 182 | 191 |
return shadow_password |
| 183 | 192 |
|
| 184 | 193 |
def ui_config(self, options_file, maxy, maxx): |
| 185 |
- # This represents the installer screen, the bool indicated if I can go back to this window or not |
|
| 186 |
- items = [] |
|
| 187 |
- random_id = '%12x' % random.randrange(16**12) |
|
| 188 |
- random_hostname = "photon-" + random_id.strip() |
|
| 194 |
+ """Configuration through UI""" |
|
| 195 |
+ # This represents the installer screen, the bool indicated if |
|
| 196 |
+ # I can go back to this window or not |
|
| 189 | 197 |
install_config = {'iso_system': False}
|
| 190 | 198 |
install_config['ui_install'] = True |
| 199 |
+ items, select_linux_index = self.add_ui_pages(options_file, maxy, maxx, |
|
| 200 |
+ install_config) |
|
| 201 |
+ index = 0 |
|
| 202 |
+ while True: |
|
| 203 |
+ result = items[index][0](None) |
|
| 204 |
+ if result.success: |
|
| 205 |
+ index += 1 |
|
| 206 |
+ if index == len(items): |
|
| 207 |
+ break |
|
| 208 |
+ #Skip linux select screen for ostree installation. |
|
| 209 |
+ if index == select_linux_index: |
|
| 210 |
+ if install_config['type'] == 'ostree_server': |
|
| 211 |
+ index += 1 |
|
| 212 |
+ else: |
|
| 213 |
+ index -= 1 |
|
| 214 |
+ while index >= 0 and items[index][1] is False: |
|
| 215 |
+ index -= 1 |
|
| 216 |
+ if index < 0: |
|
| 217 |
+ index = 0 |
|
| 218 |
+ #Skip linux select screen for ostree installation. |
|
| 219 |
+ if index == select_linux_index: |
|
| 220 |
+ if install_config['type'] == 'ostree_server': |
|
| 221 |
+ index -= 1 |
|
| 222 |
+ return install_config |
|
| 223 |
+ def add_ui_pages(self, options_file, maxy, maxx, install_config): |
|
| 224 |
+ items = [] |
|
| 191 | 225 |
license_agreement = License(maxy, maxx) |
| 192 | 226 |
select_disk = SelectDisk(maxy, maxx, install_config) |
| 193 | 227 |
select_partition = PartitionISO(maxy, maxx, install_config) |
| 194 | 228 |
package_selector = PackageSelector(maxy, maxx, install_config, options_file) |
| 195 |
- self.alpha_chars = list(range(65, 91)) |
|
| 196 |
- self.alpha_chars.extend(range(97, 123)) |
|
| 197 |
- hostname_accepted_chars = self.alpha_chars |
|
| 198 |
- # Adding the numeric chars |
|
| 199 |
- hostname_accepted_chars.extend(range(48, 58)) |
|
| 200 |
- # Adding the . and - |
|
| 201 |
- hostname_accepted_chars.extend([ord('.'), ord('-')])
|
|
| 202 |
- |
|
| 203 | 229 |
hostname_reader = WindowStringReader( |
| 204 | 230 |
maxy, maxx, 10, 70, |
| 205 | 231 |
'hostname', |
| 206 | 232 |
None, # confirmation error msg if it's a confirmation text |
| 207 | 233 |
None, # echo char |
| 208 |
- hostname_accepted_chars, # set of accepted chars |
|
| 209 |
- self.validate_hostname, # validation function of the input |
|
| 234 |
+ self.hostname_accepted_chars, # set of accepted chars |
|
| 235 |
+ IsoConfig.validate_hostname, # validation function of the input |
|
| 210 | 236 |
None, # post processing of the input field |
| 211 | 237 |
'Choose the hostname for your system', 'Hostname:', 2, install_config, |
| 212 |
- random_hostname, |
|
| 238 |
+ self.random_hostname, |
|
| 213 | 239 |
True) |
| 214 | 240 |
root_password_reader = WindowStringReader( |
| 215 | 241 |
maxy, maxx, 10, 70, |
| ... | ... |
@@ -223,7 +267,8 @@ class IsoConfig(object): |
| 223 | 223 |
confirm_password_reader = WindowStringReader( |
| 224 | 224 |
maxy, maxx, 10, 70, |
| 225 | 225 |
'password', |
| 226 |
- "Passwords don't match, please try again.", # confirmation error msg if it's a confirmation text |
|
| 226 |
+ # confirmation error msg if it's a confirmation text |
|
| 227 |
+ "Passwords don't match, please try again.", |
|
| 227 | 228 |
'*', # echo char |
| 228 | 229 |
None, # set of accepted chars |
| 229 | 230 |
None, # validation function of the input |
| ... | ... |
@@ -243,27 +288,4 @@ class IsoConfig(object): |
| 243 | 243 |
items.append((hostname_reader.get_user_string, True)) |
| 244 | 244 |
items.append((root_password_reader.get_user_string, True)) |
| 245 | 245 |
items.append((confirm_password_reader.get_user_string, False)) |
| 246 |
- index = 0 |
|
| 247 |
- params = None |
|
| 248 |
- while True: |
|
| 249 |
- result = items[index][0](params) |
|
| 250 |
- if result.success: |
|
| 251 |
- index += 1 |
|
| 252 |
- params = result.result |
|
| 253 |
- if index == len(items): |
|
| 254 |
- break |
|
| 255 |
- #Skip linux select screen for ostree installation. |
|
| 256 |
- if index == select_linux_index: |
|
| 257 |
- if install_config['type'] == 'ostree_server': |
|
| 258 |
- index += 1 |
|
| 259 |
- else: |
|
| 260 |
- index -= 1 |
|
| 261 |
- while index >= 0 and items[index][1] is False: |
|
| 262 |
- index -= 1 |
|
| 263 |
- if index < 0: |
|
| 264 |
- index = 0 |
|
| 265 |
- #Skip linux select screen for ostree installation. |
|
| 266 |
- if index == select_linux_index: |
|
| 267 |
- if install_config['type'] == 'ostree_server': |
|
| 268 |
- index -= 1 |
|
| 269 |
- return install_config |
|
| 246 |
+ return items, select_linux_index |
| ... | ... |
@@ -6,8 +6,8 @@ PRE_INSTALL = "pre-install" |
| 6 | 6 |
POST_INSTALL = "post-install" |
| 7 | 7 |
|
| 8 | 8 |
LOG_LEVEL_DESC = ["emerg", "alert", "crit", "err", "warning", "notice", "info", "debug"] |
| 9 |
-LOG_FILE_NAME = "/var/log/installer.log" |
|
| 10 |
-TDNF_LOG_FILE_NAME = "/var/log/tdnf.log" |
|
| 9 |
+LOG_FILE_NAME = "/var/log/installer.log" |
|
| 10 |
+TDNF_LOG_FILE_NAME = "/var/log/tdnf.log" |
|
| 11 | 11 |
TDNF_CMDLINE_FILE_NAME = "/var/log/tdnf.cmdline" |
| 12 | 12 |
KS_POST_INSTALL_LOG_FILE_NAME = "/var/log/installer-kickstart.log" |
| 13 | 13 |
SIGNATURE = "localhost echo" |
| ... | ... |
@@ -21,8 +21,8 @@ LOG_INFO = 6 |
| 21 | 21 |
LOG_DEBUG = 7 |
| 22 | 22 |
|
| 23 | 23 |
default_partitions = [ |
| 24 |
- {"mountpoint": "/", "size": 0, "filesystem": "ext4"},
|
|
| 25 |
- ] |
|
| 24 |
+ {"mountpoint": "/", "size": 0, "filesystem": "ext4"},
|
|
| 25 |
+ ] |
|
| 26 | 26 |
|
| 27 | 27 |
def partition_compare(p): |
| 28 | 28 |
if 'mountpoint' in p: |
| ... | ... |
@@ -36,7 +36,7 @@ def partition_disk(disk, partitions): |
| 36 | 36 |
output = open(os.devnull, 'w') |
| 37 | 37 |
|
| 38 | 38 |
# Clear the disk |
| 39 |
- process = subprocess.Popen(['sgdisk', '-o', '-g', disk], stderr = output, stdout = output) |
|
| 39 |
+ process = subprocess.Popen(['sgdisk', '-o', '-g', disk], stderr=output, stdout=output) |
|
| 40 | 40 |
retval = process.wait() |
| 41 | 41 |
if retval != 0: |
| 42 | 42 |
log(LOG_ERROR, "Failed clearing disk {0}".format(disk))
|
| ... | ... |
@@ -58,7 +58,7 @@ def partition_disk(disk, partitions): |
| 58 | 58 |
# Adding the known size partitions |
| 59 | 59 |
for partition in partitions: |
| 60 | 60 |
if partition['size'] == 0: |
| 61 |
- # Can not have more than 1 extensible partition |
|
| 61 |
+ # Can not have more than 1 extensible partition |
|
| 62 | 62 |
if extensible_partition != None: |
| 63 | 63 |
log(LOG_ERROR, "Can not have more than 1 extensible partition") |
| 64 | 64 |
return None |
| ... | ... |
@@ -80,13 +80,13 @@ def partition_disk(disk, partitions): |
| 80 | 80 |
partition_cmd.extend(['-p', disk]) |
| 81 | 81 |
|
| 82 | 82 |
# Run the partitioning command |
| 83 |
- process = subprocess.Popen(partition_cmd, stderr = output, stdout = output) |
|
| 83 |
+ process = subprocess.Popen(partition_cmd, stderr=output, stdout=output) |
|
| 84 | 84 |
retval = process.wait() |
| 85 | 85 |
if retval != 0: |
| 86 | 86 |
log(LOG_ERROR, "Faild partition disk, command: {0}". format(partition_cmd))
|
| 87 | 87 |
return None |
| 88 | 88 |
|
| 89 |
- process = subprocess.Popen(['sgdisk', '-t1' + grub_flag, disk], stderr = output, stdout = output) |
|
| 89 |
+ process = subprocess.Popen(['sgdisk', '-t1' + grub_flag, disk], stderr=output, stdout=output) |
|
| 90 | 90 |
retval = process.wait() |
| 91 | 91 |
if retval != 0: |
| 92 | 92 |
log(LOG_ERROR, "Failed to setup grub partition") |
| ... | ... |
@@ -103,25 +103,27 @@ def partition_disk(disk, partitions): |
| 103 | 103 |
partitions_data['boot_partition_number'] = partition['partition_number'] |
| 104 | 104 |
partitions_data['bootdirectory'] = '/' |
| 105 | 105 |
if partition['filesystem'] == "swap": |
| 106 |
- process = subprocess.Popen(['mkswap', partition['path']], stderr = output, stdout = output) |
|
| 106 |
+ process = subprocess.Popen(['mkswap', partition['path']], stderr=output, stdout=output) |
|
| 107 | 107 |
retval = process.wait() |
| 108 | 108 |
if retval != 0: |
| 109 | 109 |
log(LOG_ERROR, "Failed to create swap partition @ {}".format(partition['path']))
|
| 110 | 110 |
return None |
| 111 | 111 |
else: |
| 112 | 112 |
mkfs_cmd = ['mkfs', '-t', partition['filesystem'], partition['path']] |
| 113 |
- process = subprocess.Popen(mkfs_cmd, stderr = output, stdout = output) |
|
| 113 |
+ process = subprocess.Popen(mkfs_cmd, stderr=output, stdout=output) |
|
| 114 | 114 |
retval = process.wait() |
| 115 | 115 |
if retval != 0: |
| 116 |
- log(LOG_ERROR, "Failed to format {} partition @ {}".format(partition['filesystem'], partition['path']))
|
|
| 116 |
+ log(LOG_ERROR, |
|
| 117 |
+ "Failed to format {} partition @ {}".format(partition['filesystem'],
|
|
| 118 |
+ partition['path'])) |
|
| 117 | 119 |
return None |
| 118 | 120 |
|
| 119 | 121 |
# Check if there is no root partition |
| 120 |
- if not 'root' in partitions_data: |
|
| 122 |
+ if 'root' not in partitions_data: |
|
| 121 | 123 |
log(LOG_ERROR, "There is no partition assigned to root '/'") |
| 122 | 124 |
return None |
| 123 | 125 |
|
| 124 |
- if not 'boot' in partitions_data: |
|
| 126 |
+ if 'boot' not in partitions_data: |
|
| 125 | 127 |
partitions_data['boot'] = partitions_data['root'] |
| 126 | 128 |
partitions_data['boot_partition_number'] = partitions_data['root_partition_number'] |
| 127 | 129 |
partitions_data['bootdirectory'] = '/boot/' |
| ... | ... |
@@ -130,9 +132,9 @@ def partition_disk(disk, partitions): |
| 130 | 130 |
|
| 131 | 131 |
return partitions_data |
| 132 | 132 |
|
| 133 |
-def replace_string_in_file(filename, search_string, replace_string): |
|
| 133 |
+def replace_string_in_file(filename, search_string, replace_string): |
|
| 134 | 134 |
with open(filename, "r") as source: |
| 135 |
- lines=source.readlines() |
|
| 135 |
+ lines = source.readlines() |
|
| 136 | 136 |
|
| 137 | 137 |
with open(filename, "w") as destination: |
| 138 | 138 |
for line in lines: |
| ... | ... |
@@ -145,7 +147,8 @@ def log(type, message): |
| 145 | 145 |
return retval |
| 146 | 146 |
|
| 147 | 147 |
def dump(type, filename): |
| 148 |
- command = "journalctl -p {0} | grep --line-buffered \"{1}\" > {2}".format(LOG_LEVEL_DESC[type], SIGNATURE, filename)
|
|
| 148 |
+ command = ("journalctl -p {0} | grep --line-buffered \"{1}\" > {2}"
|
|
| 149 |
+ .format(LOG_LEVEL_DESC[type], SIGNATURE, filename)) |
|
| 149 | 150 |
process = subprocess.Popen([command], shell=True) |
| 150 | 151 |
retval = process.wait() |
| 151 | 152 |
return retval |
| ... | ... |
@@ -153,5 +156,5 @@ def dump(type, filename): |
| 153 | 153 |
def dump(filename): |
| 154 | 154 |
command = "journalctl | grep --line-buffered \"{0}\" > {1}".format(SIGNATURE, filename)
|
| 155 | 155 |
process = subprocess.Popen([command], shell=True) |
| 156 |
- retval = process.wait() |
|
| 156 |
+ retval = process.wait() |
|
| 157 | 157 |
return retval |
| ... | ... |
@@ -5,7 +5,7 @@ import commons |
| 5 | 5 |
install_phase = commons.POST_INSTALL |
| 6 | 6 |
enabled = True |
| 7 | 7 |
|
| 8 |
-def execute(name, config, root): |
|
| 8 |
+def execute(config, root): |
|
| 9 | 9 |
if 'postinstall' not in config: |
| 10 | 10 |
return |
| 11 | 11 |
# run the script in the chroot environment |
| ... | ... |
@@ -13,14 +13,15 @@ def execute(name, config, root): |
| 13 | 13 |
|
| 14 | 14 |
script_file = os.path.join(root, 'etc/tmpfiles.d/postinstall.sh') |
| 15 | 15 |
|
| 16 |
- with open(script_file, 'wb') as outfile: |
|
| 16 |
+ with open(script_file, 'wb') as outfile: |
|
| 17 | 17 |
outfile.write("\n".join(script).encode())
|
| 18 | 18 |
|
| 19 |
- os.chmod(script_file, 0o700); |
|
| 20 |
- with open(commons.KS_POST_INSTALL_LOG_FILE_NAME,"w") as logfile: |
|
| 21 |
- process = subprocess.Popen(["./mk-run-chroot.sh", '-w', root, "/etc/tmpfiles.d/postinstall.sh"], |
|
| 22 |
- stdout=logfile,stderr=logfile) |
|
| 19 |
+ os.chmod(script_file, 0o700) |
|
| 20 |
+ with open(commons.KS_POST_INSTALL_LOG_FILE_NAME, "w") as logfile: |
|
| 21 |
+ process = subprocess.Popen(["./mk-run-chroot.sh", '-w', root, |
|
| 22 |
+ "/etc/tmpfiles.d/postinstall.sh"], |
|
| 23 |
+ stdout=logfile, stderr=logfile) |
|
| 23 | 24 |
retval = process.wait() |
| 24 |
- if retval==0: |
|
| 25 |
+ if retval == 0: |
|
| 25 | 26 |
return True |
| 26 | 27 |
return False |
| ... | ... |
@@ -1,11 +1,11 @@ |
| 1 | 1 |
import os |
| 2 |
-import commons |
|
| 3 | 2 |
import random |
| 3 |
+import commons |
|
| 4 | 4 |
|
| 5 | 5 |
install_phase = commons.POST_INSTALL |
| 6 | 6 |
enabled = True |
| 7 | 7 |
|
| 8 |
-def execute(name, config, root): |
|
| 8 |
+def execute(config, root): |
|
| 9 | 9 |
hostname = config['hostname'] |
| 10 | 10 |
|
| 11 | 11 |
hostname_file = os.path.join(root, 'etc/hostname') |
| ... | ... |
@@ -1,26 +1,25 @@ |
| 1 | 1 |
import os |
| 2 |
-import commons |
|
| 3 | 2 |
import crypt |
| 4 | 3 |
import random |
| 5 | 4 |
import string |
| 5 |
+import commons |
|
| 6 | 6 |
|
| 7 | 7 |
install_phase = commons.POST_INSTALL |
| 8 | 8 |
enabled = True |
| 9 | 9 |
|
| 10 |
-def execute(name, config, root): |
|
| 10 |
+def execute(config, root): |
|
| 11 | 11 |
shadow_password = config['password'] |
| 12 | 12 |
|
| 13 | 13 |
passwd_filename = os.path.join(root, 'etc/passwd') |
| 14 | 14 |
shadow_filename = os.path.join(root, 'etc/shadow') |
| 15 |
- |
|
| 15 |
+ |
|
| 16 | 16 |
#replace root blank password in passwd file to point to shadow file |
| 17 |
- commons.replace_string_in_file(passwd_filename, "root::", "root:x:") |
|
| 17 |
+ commons.replace_string_in_file(passwd_filename, "root::", "root:x:") |
|
| 18 | 18 |
|
| 19 | 19 |
if os.path.isfile(shadow_filename) == False: |
| 20 | 20 |
with open(shadow_filename, "w") as destination: |
| 21 |
- destination.write("root:"+shadow_password+":")
|
|
| 21 |
+ destination.write("root:" + shadow_password + ":")
|
|
| 22 | 22 |
else: |
| 23 | 23 |
#add password hash in shadow file |
| 24 | 24 |
commons.replace_string_in_file(shadow_filename, "root::", "root:"+shadow_password+":") |
| 25 | 25 |
commons.replace_string_in_file(shadow_filename, "root:x:", "root:"+shadow_password+":") |
| 26 |
- |
| ... | ... |
@@ -5,7 +5,7 @@ import commons |
| 5 | 5 |
install_phase = commons.POST_INSTALL |
| 6 | 6 |
enabled = True |
| 7 | 7 |
|
| 8 |
-def execute(name, config, root): |
|
| 8 |
+def execute(config, root): |
|
| 9 | 9 |
if 'public_key' not in config: |
| 10 | 10 |
return |
| 11 | 11 |
|
| ... | ... |
@@ -21,5 +21,6 @@ def execute(name, config, root): |
| 21 | 21 |
os.chmod(authorized_keys_filename, 0o600) |
| 22 | 22 |
|
| 23 | 23 |
# Change the sshd config to allow root login |
| 24 |
- process = subprocess.Popen(["sed", "-i", "s/^\\s*PermitRootLogin\s\+no/PermitRootLogin yes/", sshd_config_filename]) |
|
| 24 |
+ process = subprocess.Popen(["sed", "-i", "s/^\\s*PermitRootLogin\s\+no/PermitRootLogin yes/", |
|
| 25 |
+ sshd_config_filename]) |
|
| 25 | 26 |
return process.wait() |