]>
git.ipfire.org Git - people/ms/bricklayer.git/blob - src/python/__init__.py
1 ###############################################################################
3 # Bricklayer - An Installer for IPFire #
4 # Copyright (C) 2021 IPFire Development Team #
6 # This program is free software; you can redistribute it and/or #
7 # modify it under the terms of the GNU General Public License #
8 # as published by the Free Software Foundation; either version 2 #
9 # of the License, or (at your option) any later version. #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 ###############################################################################
29 from . import bootloaders
33 from . import packages
35 from . import timezones
42 log
= logging
.getLogger("bricklayer")
44 class Bricklayer(object):
46 Bricklayer's base class
48 def __init__(self
, arch
, first_install
=False, debug
=False, unattended
=False, disks
=[]):
50 self
.first_install
= first_install
52 self
.unattended
= unattended
54 # Enable debug logging
56 log
.setLevel(logging
.DEBUG
)
60 "language" : i18n
.default_language
,
63 # Install the Base group
67 # Set the default swap size to 1 GiB
68 "swap-size": 1024 ** 3,
75 self
.os
= self
._read
_os
_release
()
77 # Select a bootloaders
78 self
.bootloaders
= self
._select
_bootloaders
()
81 self
.disks
= disk
.Disks(self
)
83 self
.disks
.add_disk(path
)
85 # Initialise the text user interface
86 self
.tui
= tui
.Tui(self
)
88 # Create root directory
89 self
.root
= tempfile
.mkdtemp(prefix
="bricklayer-", suffix
="-root")
91 # Log when we are ready
92 log
.info("Bricklayer initialized")
94 # An ordered list of all available steps
96 step
.UnattendedWarning
,
98 timezones
.SelectTimezone
,
100 disk
.CalculatePartitionLayout
,
104 disk
.CreatePartitionLayout
,
105 disk
.CreateFilesystems
,
106 disk
.MountFilesystems
,
107 packages
.InstallPackages
,
108 bootloaders
.InstallBootloader
,
111 step
.ToggleFirstInstallStatus
,
112 disk
.UmountFilesystems
,
113 step
.Congratulations
,
119 # Walk through all steps
120 for step
in self
.steps
:
124 # End installer if aborted
125 except InstallAbortedError
:
128 # The user requested to cancel the installation process
129 except UserCanceledError
:
131 _("Cancel Installation?"),
132 _("Are you sure that you want to cancel the installation process?"),
136 # Catch any failed commands
137 except subprocess
.CalledProcessError
as e
:
139 "command" : " ".join(e
.cmd
),
140 "output" : e
.output
.decode(),
141 "returncode" : e
.returncode
,
145 log
.error("Command \"%(command)s\" failed with error code "
146 "%(returncode)s:\n%(output)s" % args
)
148 # Format the error message
149 error
= _("Command \"%(command)s\" failed with error code "
150 "%(returncode)s:\n\n%(output)s" % args
)
153 self
.tui
.error(_("An Unexpected Error Occured"), error
,
154 buttons
=[_("Exit")], width
=78)
159 # Catch all other exceptions and show an error
161 type, value
, tb
= sys
.exc_info()
164 log
.error("An unexpected error occured:", exc_info
=True)
166 # Format the exception
167 error
= _("The installation cannot be continued due to an error:"
168 "\n\n%s") % "".join(traceback
.format_exception(type, value
, tb
))
170 # Show an error message
171 self
.tui
.error(_("An Unexpected Error Occured"),
172 "".join(error
), buttons
=[_("Exit")], width
=78)
177 # Cleanup when we leave
179 self
.disks
.tear_down()
181 def _run_step(self
, stepcls
):
185 # Initialize the step
186 step
= stepcls(self
, tui
=self
.tui
)
188 # Skip this step if it isn't enabled in first install mode
189 if self
.first_install
and not step
.first_install
:
192 # Skip this step if it isn't enabled
199 def _read_os_release(self
):
203 with
open("/etc/os-release") as f
:
204 return util
.config_read(f
)
206 def command(self
, command
, error_ok
=False, interactive
=False):
208 Runs a command in a shell environment
210 log
.debug("Running command: %s" % " ".join(command
))
216 "stdout" : subprocess
.PIPE
,
217 "stderr" : subprocess
.STDOUT
,
220 # Execute the command
221 p
= subprocess
.run(command
, **args
)
223 # Check the return code (raises CalledProcessError on non-zero)
227 # There is no output in interactive mode
232 output
= p
.stdout
.decode()
240 def setup_pakfire(self
):
242 Calls Pakfire and has it load its configuration
244 return pakfire
.Pakfire(self
.root
, arch
=self
.arch
,
245 conf
="/etc/pakfire/distros/ipfire3.conf")
247 def _select_bootloaders(self
):
249 Select all bootloaders for this installation process
252 bootloaders
.Grub(self
),
253 bootloaders
.GrubEFI(self
),
256 # Return all supported bootloaders
257 return [bl
for bl
in _bootloaders
if bl
.supported
]