From 8aa30d4512735d4a087f8235c9af9735d5a3b019 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Sun, 9 Nov 2014 22:55:32 +0000 Subject: Add manifest for installer system --- installer/bin/installer.py | 178 +++++++++++++++++++++++++++++++++++++++++++++ installer/installer.py | 178 --------------------------------------------- installer/manifest | 4 + 3 files changed, 182 insertions(+), 178 deletions(-) create mode 100755 installer/bin/installer.py delete mode 100755 installer/installer.py create mode 100644 installer/manifest diff --git a/installer/bin/installer.py b/installer/bin/installer.py new file mode 100755 index 00000000..aec43591 --- /dev/null +++ b/installer/bin/installer.py @@ -0,0 +1,178 @@ +#!/usr/bin/python +# Copyright (C) 2014 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +'''A Baserock installer.''' + + + +import morphlib +import ConfigParser +import os +import re +import sys +import json +import subprocess +import tempfile +import errno +import time + +class BaserockInstaller(): + + config_file = '/etc/install.conf' + to_mount = ( + ('/proc', 'proc', 'none'), + ('/sys', 'sysfs', 'none'), + + ) + + def run(self): + try: + print "Baserock installation script begins..." + mounted = self.do_mounts(self.to_mount) + + rawdisk_path = morphlib.extensions._get_morph_extension_filename( + 'rawdisk', '.write') + + disk_dest, rootfs = self.check_and_read_config(self.config_file) + self.validate_install_values(disk_dest, rootfs) + + deployment_config=self.get_deployment_config(rootfs) + + install_script = self.create_install_script(rawdisk_path, + deployment_config, rootfs, disk_dest) + + self.install_system(install_script) + os.remove(install_script) + self.do_unmounts(mounted) + self.finish_and_reboot() + except BaseException, e: + print "Something failed, opening shell..." + print "Once you have finished, use `reboot -f`" + os.system('/bin/sh') + + def validate_install_values(self, disk_dest, rootfs): + if not self.deploying_to_device(disk_dest): + print "ERROR: Not deploying to a device" + raise BaseException + if not os.path.exists(disk_dest): + print "ERROR: The device %s doesn't exist." % disk_dest + raise BaseException + if not self.is_baserock_rootfs(rootfs): + print "ERROR: The rootfs %s is not a baserock rootfs." % rootfs + raise BaseException + + def is_baserock_rootfs(self, rootfs): + if os.path.isdir(os.path.join(rootfs, 'baserock')): + return True + return False + + def create_install_script(self, rawdisk_path, deployment_config, + rootfs, disk_dest): + fd, script = tempfile.mkstemp() + with os.fdopen(fd, 'w') as fp: + fp.write('#!/bin/sh\n') + fp.write('env ') + for name in deployment_config: + if deployment_config[name] is not None: + fp.write('%s="%s" ' % (name, deployment_config[name])) + fp.write("%s %s %s\n" % (rawdisk_path, rootfs, disk_dest)) + return script + + def finish_and_reboot(self): + os.system("sync") + print "Rebooting in 5 seconds..." + time.sleep(5) + os.system("reboot -f") + + def do_mounts(self, to_mount): + mounted = [] + for mount_point, mount_type, source in to_mount: + print 'Mounting %s in %s' % (source, mount_point) + if not os.path.exists(mount_point): + os.makedirs(mount_point) + if self.mount( source, mount_point, mount_type) == 0: + mounted.append(mount_point) + return mounted + + def mount(self, partition, mount_point, fstype=None): + if not fstype: + fstype = '' + else: + fstype = '-t %s' % fstype + mount_command = "mount %s %s %s" % (partition, mount_point, fstype) + child = subprocess.Popen(mount_command, shell=True) + child.communicate()[0] + return child.returncode + + def do_unmounts(self, to_unmount): + for path in reversed(to_unmount): + print 'Unmounting %s' % path + unmount_command = "umount %s" % (path) + subprocess.Popen(unmount_command, shell=True) + + def check_and_read_config(self, config_file): + print "Reading configuration from %s..." % config_file + config = ConfigParser.RawConfigParser() + config.read(config_file) + keys = ('device', 'rootfs') + + device, rootfs = (self.read_option(config, 'install', key) + for key in keys) + return device, rootfs + + def read_option(self, config, section, option): + try: + value = config.get(section, option) + except: + value = raw_input("Option '%s.%s' missing, please enter a value: " + % (section, option)) + print "Option '%s.%s' with value '%s" % (section, option, value) + return value + + def get_deployment_config(self, rootfs): + print "Reading deployment.meta of the system to install..." + try: + meta = open(os.path.join(rootfs, 'baserock/deployment.meta')) + except IOError as e: + if e.errno != errno.ENOENT: + raise + print "Failed to read deployment.meta, it will be empty" + deployment_config = {} + else: + deployment_config = json.load(meta).get('configuration', {}) + meta.close() + print "################ Environment #################" + for key in deployment_config: + print "# %s: %s" % (key, deployment_config[key]) + print "##############################################" + return deployment_config + + + def install_system(self, install_script): + run_script = "sh %s" % install_script + process = subprocess.Popen(run_script, shell=True, stdout=subprocess.PIPE) + for line in iter(process.stdout.readline, ''): + sys.stdout.write(line) + + def deploying_to_device(self, location): + dev_regex = re.compile("^/dev/((sd|vd|mmcblk|hd)[a-z0-9]+)$") + if dev_regex.match(location): + return True + return False + + +BaserockInstaller().run() diff --git a/installer/installer.py b/installer/installer.py deleted file mode 100755 index aec43591..00000000 --- a/installer/installer.py +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2014 Codethink Limited -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - -'''A Baserock installer.''' - - - -import morphlib -import ConfigParser -import os -import re -import sys -import json -import subprocess -import tempfile -import errno -import time - -class BaserockInstaller(): - - config_file = '/etc/install.conf' - to_mount = ( - ('/proc', 'proc', 'none'), - ('/sys', 'sysfs', 'none'), - - ) - - def run(self): - try: - print "Baserock installation script begins..." - mounted = self.do_mounts(self.to_mount) - - rawdisk_path = morphlib.extensions._get_morph_extension_filename( - 'rawdisk', '.write') - - disk_dest, rootfs = self.check_and_read_config(self.config_file) - self.validate_install_values(disk_dest, rootfs) - - deployment_config=self.get_deployment_config(rootfs) - - install_script = self.create_install_script(rawdisk_path, - deployment_config, rootfs, disk_dest) - - self.install_system(install_script) - os.remove(install_script) - self.do_unmounts(mounted) - self.finish_and_reboot() - except BaseException, e: - print "Something failed, opening shell..." - print "Once you have finished, use `reboot -f`" - os.system('/bin/sh') - - def validate_install_values(self, disk_dest, rootfs): - if not self.deploying_to_device(disk_dest): - print "ERROR: Not deploying to a device" - raise BaseException - if not os.path.exists(disk_dest): - print "ERROR: The device %s doesn't exist." % disk_dest - raise BaseException - if not self.is_baserock_rootfs(rootfs): - print "ERROR: The rootfs %s is not a baserock rootfs." % rootfs - raise BaseException - - def is_baserock_rootfs(self, rootfs): - if os.path.isdir(os.path.join(rootfs, 'baserock')): - return True - return False - - def create_install_script(self, rawdisk_path, deployment_config, - rootfs, disk_dest): - fd, script = tempfile.mkstemp() - with os.fdopen(fd, 'w') as fp: - fp.write('#!/bin/sh\n') - fp.write('env ') - for name in deployment_config: - if deployment_config[name] is not None: - fp.write('%s="%s" ' % (name, deployment_config[name])) - fp.write("%s %s %s\n" % (rawdisk_path, rootfs, disk_dest)) - return script - - def finish_and_reboot(self): - os.system("sync") - print "Rebooting in 5 seconds..." - time.sleep(5) - os.system("reboot -f") - - def do_mounts(self, to_mount): - mounted = [] - for mount_point, mount_type, source in to_mount: - print 'Mounting %s in %s' % (source, mount_point) - if not os.path.exists(mount_point): - os.makedirs(mount_point) - if self.mount( source, mount_point, mount_type) == 0: - mounted.append(mount_point) - return mounted - - def mount(self, partition, mount_point, fstype=None): - if not fstype: - fstype = '' - else: - fstype = '-t %s' % fstype - mount_command = "mount %s %s %s" % (partition, mount_point, fstype) - child = subprocess.Popen(mount_command, shell=True) - child.communicate()[0] - return child.returncode - - def do_unmounts(self, to_unmount): - for path in reversed(to_unmount): - print 'Unmounting %s' % path - unmount_command = "umount %s" % (path) - subprocess.Popen(unmount_command, shell=True) - - def check_and_read_config(self, config_file): - print "Reading configuration from %s..." % config_file - config = ConfigParser.RawConfigParser() - config.read(config_file) - keys = ('device', 'rootfs') - - device, rootfs = (self.read_option(config, 'install', key) - for key in keys) - return device, rootfs - - def read_option(self, config, section, option): - try: - value = config.get(section, option) - except: - value = raw_input("Option '%s.%s' missing, please enter a value: " - % (section, option)) - print "Option '%s.%s' with value '%s" % (section, option, value) - return value - - def get_deployment_config(self, rootfs): - print "Reading deployment.meta of the system to install..." - try: - meta = open(os.path.join(rootfs, 'baserock/deployment.meta')) - except IOError as e: - if e.errno != errno.ENOENT: - raise - print "Failed to read deployment.meta, it will be empty" - deployment_config = {} - else: - deployment_config = json.load(meta).get('configuration', {}) - meta.close() - print "################ Environment #################" - for key in deployment_config: - print "# %s: %s" % (key, deployment_config[key]) - print "##############################################" - return deployment_config - - - def install_system(self, install_script): - run_script = "sh %s" % install_script - process = subprocess.Popen(run_script, shell=True, stdout=subprocess.PIPE) - for line in iter(process.stdout.readline, ''): - sys.stdout.write(line) - - def deploying_to_device(self, location): - dev_regex = re.compile("^/dev/((sd|vd|mmcblk|hd)[a-z0-9]+)$") - if dev_regex.match(location): - return True - return False - - -BaserockInstaller().run() diff --git a/installer/manifest b/installer/manifest new file mode 100644 index 00000000..55ff7614 --- /dev/null +++ b/installer/manifest @@ -0,0 +1,4 @@ +0040755 0 0 /bin +0100755 0 0 /bin/installer.py +0040755 0 0 /etc +0100644 0 0 /etc/install.conf -- cgit v1.2.1