1 | #!/usr/bin/perl -w
|
---|
2 | #
|
---|
3 | # pbmkbm, a project-builder.org utility to make boot media
|
---|
4 | #
|
---|
5 | # $Id$
|
---|
6 | #
|
---|
7 | # Copyright B. Cornec 2011
|
---|
8 | # Provided under the GPL v2
|
---|
9 |
|
---|
10 | # Syntax: see at end
|
---|
11 |
|
---|
12 | use strict 'vars';
|
---|
13 | use Getopt::Long qw(:config auto_abbrev no_ignore_case);
|
---|
14 | use Data::Dumper;
|
---|
15 | use English;
|
---|
16 | use File::Basename;
|
---|
17 | use File::Copy;
|
---|
18 | use ProjectBuilder::Version;
|
---|
19 | use ProjectBuilder::Base;
|
---|
20 | use ProjectBuilder::Env;
|
---|
21 | use ProjectBuilder::Conf;
|
---|
22 | use ProjectBuilder::Distribution;
|
---|
23 | use ProjectBuilder::VE;
|
---|
24 |
|
---|
25 | # Global variables
|
---|
26 | my %opts; # CLI Options
|
---|
27 |
|
---|
28 | =pod
|
---|
29 |
|
---|
30 | =head1 NAME
|
---|
31 |
|
---|
32 | pbmkbm - a project-builder.org utility to make boot media
|
---|
33 |
|
---|
34 | =head1 DESCRIPTION
|
---|
35 |
|
---|
36 | pbmkbm creates a bootable media (CD/DVD, USB device, Network, tape, ...)
|
---|
37 | with a minimal distribution in it, suited for building packages for example.
|
---|
38 | It aims at supporting all distributions supported by project-builder.org
|
---|
39 | (RHEL, RH, Fedora, OpeSUSE, SLES, Mandriva, ...)
|
---|
40 |
|
---|
41 | It is inspired by work done by Jean-Marc André around the HP SSSTK and
|
---|
42 | aim at replacing the mindi project (http://www.mondorescue.org), but
|
---|
43 | fully integrated with project-builder.org
|
---|
44 |
|
---|
45 | pbmkbm works in different phases. The first one is to check all
|
---|
46 |
|
---|
47 | pbmkbm needs to gather a certain number of components that could come
|
---|
48 | from various sources and could be put on a different target media.
|
---|
49 | We need a kernel, an initrd/initramfs for additional modules and init script,
|
---|
50 | a root filesystem and a boot configuration file.
|
---|
51 | Kernel, modules could come either from the local installed system
|
---|
52 | (typically for disaster recovery context) or from a kernel package of a
|
---|
53 | given configuration or a referenced content.
|
---|
54 | Utilities could come from busybox, local utilities or set of packages.
|
---|
55 | The root filesystem is made with them.
|
---|
56 | The initrd/initramfs could be made internaly or by calling dracut.
|
---|
57 | The boot config file is generated from analysis content or provided externally.
|
---|
58 |
|
---|
59 | =head1 SYNOPSIS
|
---|
60 |
|
---|
61 | pbmkbm [-vhq][-t boot-type [-d device]][-b boot-method][-m os-ver-arch]
|
---|
62 | [-s script][-a pkg1[,pkg2,...]] [target-dir]
|
---|
63 |
|
---|
64 | pbmkbm [--verbose][--help][--man][--quiet][--type boot-type [--device device]]
|
---|
65 | [--machine os-ver-arch][--boot boot-method]
|
---|
66 | [--script script][--add pkg1,[pkg2,...]] [target-dir]
|
---|
67 |
|
---|
68 | =head1 OPTIONS
|
---|
69 |
|
---|
70 | =over 4
|
---|
71 |
|
---|
72 | =item B<-v|--verbose>
|
---|
73 |
|
---|
74 | Print a brief help message and exits.
|
---|
75 |
|
---|
76 | =item B<-h|--help>
|
---|
77 |
|
---|
78 | Print a brief help message and exits.
|
---|
79 |
|
---|
80 | =item B<--man>
|
---|
81 |
|
---|
82 | Prints the manual page and exits.
|
---|
83 |
|
---|
84 | =item B<-q|--quiet>
|
---|
85 |
|
---|
86 | Do not print any output.
|
---|
87 |
|
---|
88 | =item B<-t|--type boot-type>
|
---|
89 |
|
---|
90 | Type of the boot device to generate. A boot-type can be:
|
---|
91 |
|
---|
92 | =over 4
|
---|
93 |
|
---|
94 | =item B<iso>
|
---|
95 |
|
---|
96 | Generate an ISO9660 image format (suitable to be burned later on or loopback mounted. Uses isolinux.
|
---|
97 |
|
---|
98 | =item B<usb>
|
---|
99 |
|
---|
100 | Generate a USB image format (typically a key of external hard drive). Uses syslinux.
|
---|
101 |
|
---|
102 | =item B<pxe>
|
---|
103 |
|
---|
104 | Generate a PXE environement (suitable to be integrated in a PXElinux configuration). Uses pxelinux.
|
---|
105 |
|
---|
106 | =back
|
---|
107 |
|
---|
108 | =item B<-d|--device device-file>
|
---|
109 |
|
---|
110 | Name of the device or file on which you want to create the boot media.
|
---|
111 |
|
---|
112 | =item B<-b|--boot boot-method>
|
---|
113 |
|
---|
114 | This is the boot method to use to create the boot media. A boot-method can be:
|
---|
115 |
|
---|
116 | =over 4
|
---|
117 |
|
---|
118 | =item B<native>
|
---|
119 |
|
---|
120 | Use the tools of the native distribution to create the boot media. No other dependency.
|
---|
121 |
|
---|
122 | =item B<ve>
|
---|
123 |
|
---|
124 | Use the project-builder.org virtual environment notion to create the boot media. No other dependency outside of the project.
|
---|
125 |
|
---|
126 | =item B<busybox>
|
---|
127 |
|
---|
128 | Use the busybox tool to create the boot media. Cf: L<http://www.busybox.net>
|
---|
129 |
|
---|
130 | =item B<dracut>
|
---|
131 |
|
---|
132 | Use the dracut tool to create the boot media. Cf: L<http://www.dracut.net>
|
---|
133 |
|
---|
134 | =back
|
---|
135 |
|
---|
136 | =item B<-s|--script script>
|
---|
137 |
|
---|
138 | Name of the script you want to execute on the related boot media at the end o the build.
|
---|
139 |
|
---|
140 | =item B<-a|--add pkg1[,pkg2,...]>
|
---|
141 |
|
---|
142 | Additional packages to add from the distribution you want to install on the related boot media
|
---|
143 | at the end of the build.
|
---|
144 |
|
---|
145 | =item B<-m|--machine os-ver-arch>
|
---|
146 |
|
---|
147 | This is the target tuple operating system-version-architecture for which you want to create the boot media.
|
---|
148 |
|
---|
149 | =back
|
---|
150 |
|
---|
151 | =head1 ARGUMENTS
|
---|
152 |
|
---|
153 | target-dir is the directory under which the boot media will be build.
|
---|
154 |
|
---|
155 | =over 4
|
---|
156 |
|
---|
157 | =back
|
---|
158 |
|
---|
159 | =head1 EXAMPLE
|
---|
160 |
|
---|
161 | To setup a USB busybox based boot media on the /dev/sdb device for a Fedora 12 distribution with an i386 architecture issue:
|
---|
162 |
|
---|
163 | pbmkbm -t usb -d /dev/sdb -m fedora-12-i386 -b busybox
|
---|
164 |
|
---|
165 | To setup an ISO image under /tmp for a RHEL 6 x86_64 distribution issue using the native environment:
|
---|
166 |
|
---|
167 | pbmkbm -t iso -d /tmp -m rhel-6-x86_64 -b ve
|
---|
168 |
|
---|
169 | =head1 WEB SITES
|
---|
170 |
|
---|
171 | The main Web site of the project is available at L<http://www.project-builder.org/>.
|
---|
172 | Bug reports should be filled using the trac instance of the project at L<http://trac.project-builder.org/>.
|
---|
173 |
|
---|
174 | =head1 USER MAILING LIST
|
---|
175 |
|
---|
176 | Cf: L<http://www.mondorescue.org/sympa/info/pb-announce> for announces and
|
---|
177 | L<http://www.mondorescue.org/sympa/info/pb-devel> for the development of the pb project.
|
---|
178 |
|
---|
179 | =head1 CONFIGURATION FILE
|
---|
180 |
|
---|
181 | Uses Project-Builder.org configuration file (/etc/pb/pb.conf or /usr/local/etc/pb/pb.conf)
|
---|
182 |
|
---|
183 | =head1 AUTHORS
|
---|
184 |
|
---|
185 | The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
|
---|
186 |
|
---|
187 | =head1 COPYRIGHT
|
---|
188 |
|
---|
189 | Project-Builder.org is distributed under the GPL v2.0 license
|
---|
190 | described in the file C<COPYING> included with the distribution.
|
---|
191 |
|
---|
192 | =cut
|
---|
193 |
|
---|
194 | # ---------------------------------------------------------------------------
|
---|
195 |
|
---|
196 | my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
|
---|
197 | my $appname = "pbmkbm";
|
---|
198 | $ENV{'PBPROJ'} = $appname;
|
---|
199 |
|
---|
200 | # Initialize the syntax string
|
---|
201 |
|
---|
202 | pb_syntax_init("$appname Version $projectbuilderver-$projectbuilderrev\n");
|
---|
203 | pb_temp_init();
|
---|
204 |
|
---|
205 | GetOptions("help|?|h" => \$opts{'h'},
|
---|
206 | "man" => \$opts{'man'},
|
---|
207 | "verbose|v+" => \$opts{'v'},
|
---|
208 | "quiet|q" => \$opts{'q'},
|
---|
209 | "log-files|l=s" => \$opts{'l'},
|
---|
210 | "script|s=s" => \$opts{'s'},
|
---|
211 | "machine|m=s" => \$opts{'m'},
|
---|
212 | "add|a=s" => \$opts{'a'},
|
---|
213 | "device|d=s" => \$opts{'d'},
|
---|
214 | "type|t=s" => \$opts{'t'},
|
---|
215 | "boot|b=s" => \$opts{'b'},
|
---|
216 | "version|V=s" => \$opts{'V'},
|
---|
217 | ) || pb_syntax(-1,0);
|
---|
218 |
|
---|
219 | if (defined $opts{'h'}) {
|
---|
220 | pb_syntax(0,1);
|
---|
221 | }
|
---|
222 | if (defined $opts{'man'}) {
|
---|
223 | pb_syntax(0,2);
|
---|
224 | }
|
---|
225 | if (defined $opts{'v'}) {
|
---|
226 | $pbdebug = $opts{'v'};
|
---|
227 | }
|
---|
228 | if (defined $opts{'q'}) {
|
---|
229 | $pbdebug=-1;
|
---|
230 | }
|
---|
231 | if (defined $opts{'l'}) {
|
---|
232 | open(pbLOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
|
---|
233 | $pbLOG = \*pbLOG;
|
---|
234 | $pbdebug = 0 if ($pbdebug == -1);
|
---|
235 | }
|
---|
236 | pb_log_init($pbdebug, $pbLOG);
|
---|
237 |
|
---|
238 | # Get VE name
|
---|
239 | $ENV{'PBV'} = $opts{'m'};
|
---|
240 |
|
---|
241 | #
|
---|
242 | # Initialize distribution info from pb conf file
|
---|
243 | #
|
---|
244 | my $pbos = pb_distro_get_context($ENV{'PBV'});
|
---|
245 | pb_log(0,"Starting boot media build for $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}\n");
|
---|
246 |
|
---|
247 | pb_env_init_pbrc(); # to get content of HOME/.pbrc
|
---|
248 |
|
---|
249 | #
|
---|
250 | # Check target dir
|
---|
251 | # Create if not existent and use default if none given
|
---|
252 | #
|
---|
253 | my $targetdir = shift @ARGV;
|
---|
254 |
|
---|
255 | #
|
---|
256 | # Check for command requirements
|
---|
257 | #
|
---|
258 | my ($req,$opt) = pb_conf_get_if("mkbmcmd","mkbmcmdopt");
|
---|
259 | pb_check_requirements($req,$opt,$appname);
|
---|
260 |
|
---|
261 | # After that we will need root access
|
---|
262 | die "$appname needs to be run as root" if ($EFFECTIVE_USER_ID != 0);
|
---|
263 |
|
---|
264 | #
|
---|
265 | # Where is our build target directory
|
---|
266 | #
|
---|
267 |
|
---|
268 | if (not defined $targetdir) {
|
---|
269 | $targetdir = "/var/cache/pbmkbm";
|
---|
270 | my ($vestdpath) = pb_conf_get("mkbmpath");
|
---|
271 | $targetdir = "$vestdpath->{'default'}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}" if (defined $vestdpath->{'default'});
|
---|
272 | }
|
---|
273 |
|
---|
274 | die pb_log(0,"No target-dir specified and no default mkbmpath found in $ENV{'PBETC'}\n") if (not defined $targetdir);
|
---|
275 |
|
---|
276 | # Point to the right subdir and create it if needed
|
---|
277 | pb_mkdir_p($targetdir) if (! -d $targetdir);
|
---|
278 |
|
---|
279 |
|
---|
280 | # Now the preparation is over, we need to do something useful :-)
|
---|
281 | # But it all depends on how we're asked to do it.
|
---|
282 | #
|
---|
283 | # First we need to copy into the target dir all the relevant content
|
---|
284 | pb_mkbm_create_content();
|
---|
285 |
|
---|
286 | # Then we need to package this content in the destination format
|
---|
287 | pb_mkbm_create_media();
|
---|
288 |
|
---|
289 | sub pb_mkbm_create_content {
|
---|
290 |
|
---|
291 | pb_log(1,"Creating boot media content\n");
|
---|
292 |
|
---|
293 | # If not defined use VE mode by default
|
---|
294 | $opts{'b'} = "ve" if (not defined $opts{'b'});
|
---|
295 |
|
---|
296 | if ($opts{'b'} eq "ve") {
|
---|
297 | # Use existing tools to create a good VE !
|
---|
298 | pb_ve_launch($ENV{'PBV'},1);
|
---|
299 | } elsif ($opts{'b'} eq "native") {
|
---|
300 | # Use native tools to create a good VE !
|
---|
301 | } else {
|
---|
302 | die "Unknown method $opts{'b'} used to create the media content";
|
---|
303 | }
|
---|
304 |
|
---|
305 | # Once the environment is made, add what is needed for this boot media to it.
|
---|
306 | }
|
---|
307 |
|
---|
308 | sub pb_mkbm_create_media {
|
---|
309 |
|
---|
310 | }
|
---|
311 |
|
---|
312 | # Get the package list to download, store them in a cache directory
|
---|
313 | #
|
---|
314 | #my ($mkbmcachedir) = pb_conf_get_if("mkbmcachedir");
|
---|
315 | #my ($pkgs) = pb_distro_get_param($pbos,pb_conf_get("mkbmmindep"));
|
---|
316 |
|
---|
317 | #
|
---|
318 | # /proc needed
|
---|
319 | #
|
---|
320 | #pb_system("mount -o bind /proc $targetdir/proc","Mounting /proc");
|
---|
321 |
|
---|
322 | # Installed additional packages we were asked to
|
---|
323 | #if (defined $opts{'a'}) {
|
---|
324 | #$opts{'a'} =~ s/,/ /g;
|
---|
325 | #pb_system("chroot $targetdir /bin/bash -c \"$pbos->{'install'} $opts{'a'} \"","Adding packages to OS by running $pbos->{'install'} $opts{'a'}");
|
---|
326 | #}
|
---|
327 |
|
---|
328 | #
|
---|
329 | # Clean up
|
---|
330 | #
|
---|
331 | #pb_log(1,"Cleaning up\n");
|
---|
332 | #pb_system("umount $targetdir/proc","Unmounting /proc");
|
---|
333 |
|
---|
334 | # Executes post-install step if asked for
|
---|
335 | #if ($opts{'s'}) {
|
---|
336 | #pb_system("$opts{'s'} $targetdir","Executing the post-install script: $opts{'s'} $targetdir");
|
---|
337 | #}
|
---|