initial commit

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
Christian Brauner 2018-02-21 14:51:18 +01:00
commit 711ed73634
No known key found for this signature in database
GPG Key ID: 8EB056D53EECB12D
69 changed files with 16090 additions and 0 deletions

1
AUTHORS Normal file
View File

@ -0,0 +1 @@
IBM Corporation.

107
CONTRIBUTING Normal file
View File

@ -0,0 +1,107 @@
Contributing to this project
----------------------------
This project accepts contributions. In order to contribute, you should
pay attention to a few things:
1 - your code must follow the coding style rules
2 - the format of the submission must Github pull requests
3 - your work must be signed
Coding Style:
-------------
The coding style follows the Linux kernel coding style.
The coding style is defined in the 'CodingStyle' file, available in
the directory 'Documentation' of the Linux kernel source tree.
It can be accessed online too:
https://www.kernel.org/doc/html/v4.10/process/coding-style.html
Submitting Modifications:
-------------------------
The contributions must be Github pull requests.
Licensing for new files:
------------------------
LXC is made of files shipped under a few different licenses.
Anything that ends up being part of the LXC library needs to be released
under LGPLv2.1+ or a license compatible with it (though the latter will
only be accepted for cases where the code originated elsewhere and was
imported into LXC).
Language bindings for the libraries need to be released under LGPLv2.1+.
Anything else (non-libaries) needs to be Free Software and needs to be
allowed to link with LGPLv2.1+ code (if needed). LXC upstream prefers
LGPLv2.1+ or GPLv2 for those.
When introducing a new file into the project, please make sure it has a
copyright header making clear under which license it's being released
and if it doesn't match the criteria described above, please explain
your decision on the lxc-devel mailing-list when submitting your patch.
Developer Certificate of Origin:
--------------------------------
To improve tracking of contributions to this project we will use a
process modeled on the modified DCO 1.1 and use a "sign-off" procedure.
The sign-off is a simple line at the end of the explanation for the
patch, which certifies that you wrote it or otherwise have the right
to pass it on as an open-source patch. The rules are pretty simple:
if you can certify the below:
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I have
the right to submit it under the open source license indicated in
the file; or
(b) The contribution is based upon previous work that, to the best of
my knowledge, is covered under an appropriate open source License
and I have the right under that license to submit that work with
modifications, whether created in whole or in part by me, under
the same open source license (unless I am permitted to submit
under a different license), as indicated in the file; or
(c) The contribution was provided directly to me by some other person
who certified (a), (b) or (c) and I have not modified it.
(d) The contribution is made free of any other party's intellectual
property claims or rights.
(e) I understand and agree that this project and the contribution are
public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
then you just add a line saying
Signed-off-by: Random J Developer <random@developer.org>
You can do it by using option -s or --signoff when you commit
git commit --signoff ...
using your real name (sorry, no pseudonyms or anonymous contributions.)
In addition we support the following DCOs which maintainers can use to indicate
that a patch is acceptable:
Acked-by: Random J Developer <random@developer.org>
Reviewed-by: Random J Developer <random@developer.org>
If you are contributing as a group who is implementing a feature together such
that it cannot be reasonably attributed to a single developer please use:
Co-developed-by: Random J Developer 1 <random_1@developer.org>
Co-developed-by: Random J Developer 2 <random_1@developer.org>

502
COPYING Normal file
View File

@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

239
INSTALL Normal file
View File

@ -0,0 +1,239 @@
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
2006 Free Software Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
Briefly, the shell commands `./autogen.sh; ./configure; make; make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
0. If the sources are not coming from a package maintainer and the
'configure' file does not exist, you should run './autogen.sh' in
the directory containing the package's source code in order to
generate the 'configure' file from the 'configure.ac' file.
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that the
`configure' script does not know about. Run `./configure --help' for
details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out automatically,
but needs to determine by the type of machine the package will run on.
Usually, assuming the package is built to be run on the _same_
architectures, `configure' can figure that out, but if it prints a
message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share, you
can create a site shell script called `config.site' that gives default
values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf bug. Until the bug is fixed you can use this workaround:
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

12
MAINTAINERS Normal file
View File

@ -0,0 +1,12 @@
Before submitting your patches, check they are signed-off-by
conforming with the DCO contained in the ./CONTRIBUTING file.
Maintainer
----------
Committers : Serge Hallyn, Stéphane Graber, Dwight Engen and Christian Brauner
Mail patches to : lxc-devel@lists.linuxcontainers.org
Send pull requests at : https://github.com/lxc/lxc
Mailing lists : lxc-devel@lists.linuxcontainers.org, lxc-users@lists.linuxcontainers.org
Web page : https://linuxcontainers.org/lxc
GIT location : git://github.com/lxc/lxc

18
Makefile.am Normal file
View File

@ -0,0 +1,18 @@
# Makefile.am
ACLOCAL_AMFLAGS = -I config
LIBTOOL_DEPS = @LIBTOOL_DEPS@
SUBDIRS = config templates
DIST_SUBDIRS = config templates
EXTRA_DIST = \
autogen.sh \
CONTRIBUTING \
MAINTAINERS
install-data-local:
$(MKDIR_P) $(DESTDIR)$(LXCPATH)
$(MKDIR_P) $(DESTDIR)$(localstatedir)/cache/lxc
ChangeLog::
@touch ChangeLog

0
NEWS Normal file
View File

0
README Normal file
View File

29
autogen.sh Executable file
View File

@ -0,0 +1,29 @@
#!/bin/sh
#
# lxc: linux Container library
#
# (C) Copyright IBM Corp. 2007, 2008
#
# Authors:
# Daniel Lezcano <daniel.lezcano at free.fr>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
set -x
test -d autom4te.cache && rm -rf autom4te.cache
aclocal -I config || exit 1
autoconf || exit 1
automake --add-missing --copy || exit 1

37
config/Makefile.am Normal file
View File

@ -0,0 +1,37 @@
templatesconfigdir=@LXCTEMPLATECONFIG@
templatesconfig_DATA = \
alpine.common.conf \
alpine.userns.conf \
archlinux.common.conf \
archlinux.userns.conf \
centos.common.conf \
centos.userns.conf \
debian.common.conf \
debian.userns.conf \
fedora.common.conf \
fedora.userns.conf \
gentoo.common.conf \
gentoo.moresecure.conf \
gentoo.userns.conf \
opensuse.common.conf \
opensuse.userns.conf \
oracle.common.conf \
oracle.userns.conf \
plamo.common.conf \
plamo.userns.conf \
slackware.common.conf \
slackware.userns.conf \
ubuntu-cloud.common.conf \
ubuntu-cloud.lucid.conf \
ubuntu-cloud.userns.conf \
ubuntu.common.conf \
ubuntu.lucid.conf \
ubuntu.userns.conf \
openwrt.common.conf \
sparclinux.common.conf \
sparclinux.userns.conf \
voidlinux.common.conf \
voidlinux.userns.conf \
sabayon.common.conf \
sabayon.userns.conf

137
config/acinclude.m4 Normal file
View File

@ -0,0 +1,137 @@
dnl as-ac-expand.m4 0.2.0
dnl autostars m4 macro for expanding directories using configure's prefix
dnl thomas@apestaart.org
dnl
dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR)
dnl example
dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local
AC_DEFUN([AS_AC_EXPAND],
[
EXP_VAR=[$1]
FROM_VAR=[$2]
dnl first expand prefix and exec_prefix if necessary
prefix_save=$prefix
exec_prefix_save=$exec_prefix
dnl if no prefix given, then use /usr/local, the default prefix
if test "x$prefix" = "xNONE"; then
prefix="$ac_default_prefix"
fi
dnl if no exec_prefix given, then use prefix
if test "x$exec_prefix" = "xNONE"; then
exec_prefix=$prefix
fi
full_var="$FROM_VAR"
dnl loop until it doesn't change anymore
while true; do
new_full_var="`eval echo $full_var`"
if test "x$new_full_var" = "x$full_var"; then break; fi
full_var=$new_full_var
done
dnl clean up
full_var=$new_full_var
AC_SUBST([$1], "$full_var")
dnl restore prefix and exec_prefix
prefix=$prefix_save
exec_prefix=$exec_prefix_save
])
dnl Available from the GNU Autoconf Macro Archive at:
dnl http://www.gnu.org/software/ac-archive/htmldoc/ax_compare_version.html
AC_DEFUN([AX_COMPARE_VERSION], [
# Used to indicate true or false condition
ax_compare_version=false
# Convert the two version strings to be compared into a format that
# allows a simple string comparison. The end result is that a version
# string of the form 1.12.5-r617 will be converted to the form
# 0001001200050617. In other words, each number is zero padded to four
# digits, and non digits are removed.
AS_VAR_PUSHDEF([A],[ax_compare_version_A])
A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
-e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
-e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
-e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
-e 's/[[^0-9]]//g'`
AS_VAR_PUSHDEF([B],[ax_compare_version_B])
B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
-e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
-e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
-e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
-e 's/[[^0-9]]//g'`
dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary
dnl # then the first line is used to determine if the condition is true.
dnl # The sed right after the echo is to remove any indented white space.
m4_case(m4_tolower($2),
[lt],[
ax_compare_version=`echo "x$A
x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"`
],
[gt],[
ax_compare_version=`echo "x$A
x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"`
],
[le],[
ax_compare_version=`echo "x$A
x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"`
],
[ge],[
ax_compare_version=`echo "x$A
x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"`
],[
dnl Split the operator from the subversion count if present.
m4_bmatch(m4_substr($2,2),
[0],[
# A count of zero means use the length of the shorter version.
# Determine the number of characters in A and B.
ax_compare_version_len_A=`echo "$A" | awk '{print(length)}'`
ax_compare_version_len_B=`echo "$B" | awk '{print(length)}'`
# Set A to no more than B's length and B to no more than A's length.
A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"`
B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"`
],
[[0-9]+],[
# A count greater than zero means use only that many subversions
A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
],
[.+],[
AC_WARNING(
[illegal OP numeric parameter: $2])
],[])
# Pad zeros at end of numbers to make same length.
ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`"
B="$B`echo $A | sed 's/./0/g'`"
A="$ax_compare_version_tmp_A"
# Check for equality or inequality as necessary.
m4_case(m4_tolower(m4_substr($2,0,2)),
[eq],[
test "x$A" = "x$B" && ax_compare_version=true
],
[ne],[
test "x$A" != "x$B" && ax_compare_version=true
],[
AC_WARNING([illegal OP parameter: $2])
])
])
AS_VAR_POPDEF([A])dnl
AS_VAR_POPDEF([B])dnl
dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE.
if test "$ax_compare_version" = "true" ; then
m4_ifvaln([$4],[$4],[:])dnl
m4_ifvaln([$5],[else $5])dnl
fi
]) dnl AX_COMPARE_VERSION

View File

@ -0,0 +1,24 @@
# This derives from the global common config.
lxc.include = @LXCTEMPLATECONFIG@/common.conf
# Doesn't support consoles in /dev/lxc/.
lxc.tty.dir =
# Drop another (potentially) harmful capabilities.
lxc.cap.drop = audit_write
lxc.cap.drop = ipc_owner
lxc.cap.drop = mknod
lxc.cap.drop = setpcap
lxc.cap.drop = sys_nice
lxc.cap.drop = sys_pacct
lxc.cap.drop = sys_rawio
lxc.cap.drop = sys_resource
lxc.cap.drop = sys_tty_config
lxc.cap.drop = syslog
lxc.cap.drop = wake_alarm
# Mount /run as tmpfs.
lxc.mount.entry=run run tmpfs rw,nodev,relatime,mode=755 0 0
# Mount /dev/shm as tmpfs; needed for building python and possibly other packages.
lxc.mount.entry=shm dev/shm tmpfs rw,nodev,noexec,nosuid,relatime,mode=1777,create=dir 0 0

View File

@ -0,0 +1,2 @@
# This derives from the global userns config.
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -0,0 +1,31 @@
# This derives from the global common config
lxc.include = @LXCTEMPLATECONFIG@/common.conf
# Allow for 6 tty devices by default
lxc.tty.max = 6
# Set the halt/stop signals
lxc.signal.halt=SIGRTMIN+4
# Uncomment to disable creating tty devices subdirectory in /dev
# lxc.tty.dir =
# Capabilities
# Uncomment these if you don't run anything that needs the capability, and
# would like the container to run with less privilege.
#
# Dropping sys_admin disables container root from doing a lot of things
# that could be bad like re-mounting lxc fstab entries rw for example,
# but also disables some useful things like being able to nfs mount, and
# things that are already namespaced with ns_capable() kernel checks, like
# hostname(1).
# lxc.cap.drop = sys_admin
# lxc.cap.drop = net_raw # breaks dhcp/ping
# lxc.cap.drop = setgid # breaks login (initgroups/setgroups)
# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd)
# lxc.cap.drop = setuid # breaks sshd,nfs statd
# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed)
# lxc.cap.drop = audit_write
# lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd
#
lxc.cap.drop = setfcap sys_nice sys_pacct sys_rawio

View File

@ -0,0 +1,2 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -0,0 +1,20 @@
# This derives from the global common config
lxc.include = @LXCTEMPLATECONFIG@/common.conf
# Capabilities
# Uncomment these if you don't run anything that needs the capability, and
# would like the container to run with less privilege.
#
# Dropping sys_admin disables container root from doing a lot of things
# that could be bad like re-mounting lxc fstab entries rw for example,
# but also disables some useful things like being able to nfs mount, and
# things that are already namespaced with ns_capable() kernel checks, like
# hostname(1).
# lxc.cap.drop = sys_admin
# lxc.cap.drop = net_raw # breaks dhcp/ping
# lxc.cap.drop = setgid # breaks login (initgroups/setgroups)
# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd)
# lxc.cap.drop = setuid # breaks sshd,nfs statd
# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed)
# lxc.cap.drop = audit_write
lxc.cap.drop = sys_nice sys_pacct sys_rawio

View File

@ -0,0 +1,2 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -0,0 +1,28 @@
# This derives from the global common config
lxc.include = @LXCTEMPLATECONFIG@/common.conf
# Doesn't support consoles in /dev/lxc/
lxc.tty.dir =
# When using LXC with apparmor, the container will be confined by default.
# If you wish for it to instead run unconfined, copy the following line
# (uncommented) to the container's configuration file.
#lxc.apparmor.profile = unconfined
# If you wish to allow mounting block filesystems, then use the following
# line instead, and make sure to grant access to the block device and/or loop
# devices below in lxc.cgroup.devices.allow.
#lxc.apparmor.profile = lxc-container-default-with-mounting
# Extra cgroup device access
## rtc
lxc.cgroup.devices.allow = c 254:0 rm
## tun
lxc.cgroup.devices.allow = c 10:200 rwm
## hpet
lxc.cgroup.devices.allow = c 10:228 rwm
## kvm
lxc.cgroup.devices.allow = c 10:232 rwm
## To use loop devices, copy the following line to the container's
## configuration file (uncommented).
#lxc.cgroup.devices.allow = b 7:* rwm

View File

@ -0,0 +1,2 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -0,0 +1,21 @@
# This derives from the global common config
lxc.include = @LXCTEMPLATECONFIG@/common.conf
# Capabilities
# Uncomment these if you don't run anything that needs the capability, and
# would like the container to run with less privilege.
#
# Dropping sys_admin disables container root from doing a lot of things
# that could be bad like re-mounting lxc fstab entries rw for example,
# but also disables some useful things like being able to nfs mount, and
# things that are already namespaced with ns_capable() kernel checks, like
# hostname(1).
# lxc.cap.drop = sys_admin
# lxc.cap.drop = net_raw # breaks dhcp/ping
# lxc.cap.drop = setgid # breaks login (initgroups/setgroups)
# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd)
# lxc.cap.drop = setuid # breaks sshd,nfs statd
# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed)
# lxc.cap.drop = audit_write
# lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd
lxc.cap.drop = setfcap sys_nice sys_pacct sys_rawio

View File

@ -0,0 +1,2 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -0,0 +1,27 @@
# This derives from the global common config
lxc.include = @LXCTEMPLATECONFIG@/common.conf
# Gentoo common default configuration
# This is the most feature-full container configuration
# But security is not the goal.
# Looking for more security, see gentoo.moresecure.conf
# Doesn't support consoles in /dev/lxc/
lxc.tty.dir =
# Extra cgroup device access
## rtc
lxc.cgroup.devices.allow = c 254:0 rm
## tun
lxc.cgroup.devices.allow = c 10:200 rwm
## hpet
lxc.cgroup.devices.allow = c 10:228 rwm
## kvm
lxc.cgroup.devices.allow = c 10:232 rwm
## To use loop devices, copy the following line to the container's
## configuration file (uncommented).
#lxc.cgroup.devices.allow = b 7:* rwm
# /dev/shm needs to be mounted as tmpfs. It's needed by python (bug #496328)
# and possibly other packages.
lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir

View File

@ -0,0 +1,45 @@
# This derives from the global common config
lxc.include = @LXCTEMPLATECONFIG@/common.conf
# Gentoo security oriented default configuration
# This is a more security oriented container configuration
# "More" because this is far from fully secure
# Looking for more working features and you trust your
# Container user ? see gentoo.common.conf
# do not mount sysfs, see http://blog.bofh.it/debian/id_413
lxc.mount.entry=mqueue dev/mqueue mqueue rw,nodev,noexec,nosuid,create=dir 0 0
lxc.mount.entry=shm dev/shm tmpfs rw,nosuid,nodev,noexec,relatime,create=dir 0 0
lxc.mount.entry=run run tmpfs rw,nosuid,nodev,relatime,mode=755 0 0
# Capabilities
# Uncomment these if you don't run anything that needs the capability, and
# would like the container to run with less privilege.
#
# Dropping sys_admin disables container root from doing a lot of things
# that could be bad like re-mounting lxc fstab entries rw for example,
# but also disables some useful things like being able to nfs mount, and
# things that are already namespaced with ns_capable() kernel checks, like
# hostname(1).
# lxc.cap.drop = sys_admin # breaks systemd
# lxc.cap.drop = net_raw # breaks dhcp/ping
# lxc.cap.drop = setgid # breaks login (initgroups/setgroups)
# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd)
# lxc.cap.drop = setuid # breaks sshd,nfs statd
# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed)
# lxc.cap.drop = audit_write
# lxc.cap.drop = setpcap # breaks journald
# lxc.cap.drop = sys_resource # breaks systemd
# lxc.cap.drop = sys_boot # breaks sysvinit
lxc.cap.drop = audit_control audit_write dac_read_search fsetid ipc_owner linux_immutable mknod setfcap setpcap sys_admin sys_nice sys_pacct sys_ptrace sys_rawio sys_resource sys_tty_config syslog
# WARNING: the security vulnerability reported for 'cap_net_admin' at
# http://mainisusuallyafunction.blogspot.com/2012/11/attacking-hardened-linux-systems-with.html
# via JIT spraying (the BPF JIT module disabled on most systems was used
# in the example, but others are suggested vulnerable) meant that users
# with root in a container, that capability and kernel module may escape
# the container. ALWAYS be extremely careful granting any process root
# within a container, use a minimal configuration at all levels -
# including the kernel - and multiple layers of security on any system
# where security is a priority. note that not only LXC but PAX (and
# others?) were vulnerable to this issue.

View File

@ -0,0 +1,2 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -0,0 +1,22 @@
# This derives from the global common config
lxc.include = @LXCTEMPLATECONFIG@/common.conf
# Capabilities
# Uncomment these if you don't run anything that needs the capability, and
# would like the container to run with less privilege.
#
# Dropping sys_admin disables container root from doing a lot of things
# that could be bad like re-mounting lxc fstab entries rw for example,
# but also disables some useful things like being able to nfs mount, and
# things that are already namespaced with ns_capable() kernel checks, like
# hostname(1).
# lxc.cap.drop = sys_admin
# lxc.cap.drop = net_raw # breaks dhcp/ping
# lxc.cap.drop = setgid # breaks login (initgroups/setgroups)
# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd)
# lxc.cap.drop = setuid # breaks sshd,nfs statd
# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed)
# lxc.cap.drop = audit_write
# lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd
# lxc.cap.drop = setfcap
lxc.cap.drop = sys_nice sys_pacct sys_rawio

View File

@ -0,0 +1,2 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -0,0 +1,50 @@
# Default console settings
lxc.tty.dir = lxc
lxc.tty.max = 4
lxc.pty.max = 1024
# Default capabilities
lxc.cap.drop = mac_admin
lxc.cap.drop = mac_override
lxc.cap.drop = sys_admin
lxc.cap.drop = sys_module
lxc.cap.drop = sys_nice
lxc.cap.drop = sys_pacct
lxc.cap.drop = sys_ptrace
lxc.cap.drop = sys_rawio
lxc.cap.drop = sys_resource
lxc.cap.drop = sys_time
lxc.cap.drop = sys_tty_config
lxc.cap.drop = syslog
lxc.cap.drop = wake_alarm
# Default cgroups - all denied except those whitelisted
lxc.cgroup.devices.deny = a
## /dev/null and zero
lxc.cgroup.devices.allow = c 1:3 rwm
lxc.cgroup.devices.allow = c 1:5 rwm
## consoles
lxc.cgroup.devices.allow = c 5:0 rwm
lxc.cgroup.devices.allow = c 5:1 rwm
## /dev/{,u}random
lxc.cgroup.devices.allow = c 1:8 rwm
lxc.cgroup.devices.allow = c 1:9 rwm
## /dev/pts/*
lxc.cgroup.devices.allow = c 5:2 rwm
lxc.cgroup.devices.allow = c 136:* rwm
## rtc
lxc.cgroup.devices.allow = c 254:0 rm
## tun
lxc.cgroup.devices.allow = c 10:200 rwm
## dev/tty0
lxc.cgroup.devices.allow = c 4:0 rwm
## dev/tty1
lxc.cgroup.devices.allow = c 4:1 rwm
## To use loop devices, copy the following line to the container's
## configuration file (uncommented).
#lxc.cgroup.devices.allow = b 7:* rwm
# Blacklist some syscalls which are not safe in privileged
# containers
lxc.seccomp.profile = /usr/share/lxc/config/common.seccomp

View File

@ -0,0 +1,20 @@
# This derives from the global common config
lxc.include = @LXCTEMPLATECONFIG@/common.conf
# Capabilities
# Uncomment these if you don't run anything that needs the capability, and
# would like the container to run with less privilege.
#
# Dropping sys_admin disables container root from doing a lot of things
# that could be bad like re-mounting lxc fstab entries rw for example,
# but also disables some useful things like being able to nfs mount, and
# things that are already namespaced with ns_capable() kernel checks, like
# hostname(1).
# lxc.cap.drop = sys_admin
# lxc.cap.drop = net_raw # breaks dhcp/ping
# lxc.cap.drop = setgid # breaks login (initgroups/setgroups)
# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd)
# lxc.cap.drop = setuid # breaks sshd,nfs statd
# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed)
# lxc.cap.drop = audit_write
lxc.cap.drop = sys_nice sys_pacct sys_rawio

View File

@ -0,0 +1,2 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -0,0 +1,9 @@
# This derives from the global common config
lxc.include = @LXCTEMPLATECONFIG@/common.conf
# Doesn't support consoles in /dev/lxc/
lxc.tty.dir =
# Extra cgroup device access
## rtc
lxc.cgroup.devices.allow = c 254:0 rm

View File

@ -0,0 +1,2 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -0,0 +1,79 @@
# Default configuration for Sabayon containers
# Setup the default mounts
lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
# Allow for 1024 pseudo terminals
lxc.pty.max = 1024
# Setup 1 tty devices for lxc-console command
lxc.tty.max = 1
# Needed for systemd distro
lxc.autodev = 1
# Doesn't support consoles in /dev/lxc/
lxc.tty.dir =
# CGroup whitelist
lxc.cgroup.devices.deny = a
## Allow any mknod (but not reading/writing the node)
#lxc.cgroup.devices.allow = c *:* m
#lxc.cgroup.devices.allow = b *:* m
## Allow specific devices
### /dev/null
lxc.cgroup.devices.allow = c 1:3 rwm
### /dev/zero
lxc.cgroup.devices.allow = c 1:5 rwm
### /dev/full
lxc.cgroup.devices.allow = c 1:7 rwm
### /dev/random
lxc.cgroup.devices.allow = c 1:8 rwm
### /dev/urandom
lxc.cgroup.devices.allow = c 1:9 rwm
### /dev/pts/*
#lxc.cgroup.devices.allow = c 136:* rwm
### /dev/tty
#lxc.cgroup.devices.allow = c 5:0 rwm
### /dev/console
#lxc.cgroup.devices.allow = c 5:1 rwm
### /dev/ptmx
#lxc.cgroup.devices.allow = c 5:2 rwm
### fuse
#lxc.cgroup.devices.allow = c 10:229 rwm
## To use loop devices, copy the following line to the container's
## configuration file (uncommented).
#lxc.cgroup.devices.allow = b 7:* rwm
## rtc
#lxc.cgroup.devices.allow = c 254:0 rm
## tun
#lxc.cgroup.devices.allow = c 10:200 rwm
## hpet
#lxc.cgroup.devices.allow = c 10:228 rwm
## kvm
#lxc.cgroup.devices.allow = c 10:232 rwm
## /dev/mem
#lxc.cgroup.devices.allow = c 1:1 rwm
# If something doesn't work, try to comment this out.
# Dropping sys_admin disables container root from doing a lot of things
# that could be bad like re-mounting lxc fstab entries rw for example,
# but also disables some useful things like being able to nfs mount, and
# things that are already namespaced with ns_capable() kernel checks, like
# hostname(1).
lxc.cap.drop = sys_time sys_module sys_rawio mac_admin mac_override
#lxc.cap.drop = sys_admin
# /dev/shm needs to be mounted as tmpfs. It's needed by python (bug #496328)
# and possibly other packages.
lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir
# Blacklist some syscalls which are not safe in privileged
# containers
lxc.seccomp.profile = @LXCTEMPLATECONFIG@/common.seccomp
# Customize lxc options through common directory
lxc.include = @LXCTEMPLATECONFIG@/common.conf.d/

View File

@ -0,0 +1,2 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -0,0 +1,46 @@
# This derives from the global common config
lxc.include = @LXCTEMPLATECONFIG@/common.conf
# Doesn't support consoles in /dev/lxc/
lxc.tty.dir =
# Extra cgroup device access
## rtc
lxc.cgroup.devices.allow = c 254:0 rm
## tun
lxc.cgroup.devices.allow = c 10:200 rwm
## hpet
lxc.cgroup.devices.allow = c 10:228 rwm
## kvm
lxc.cgroup.devices.allow = c 10:232 rwm
## To use loop devices, copy the following line to the container's
## configuration file (uncommented).
#lxc.cgroup.devices.allow = b 7:* rwm
# mount /dev/shm as tmpfs
lxc.mount.entry = none dev/shm tmpfs rw,nosuid,nodev,create=dir
# Capabilities
# Uncomment these if you don't run anything that needs the capability, and
# would like the container to run with less privilege.
# Note that some are already dropped in common.conf.
#
# Dropping sys_admin disables container root from doing a lot of things
# that could be bad like re-mounting lxc fstab entries rw for example,
# but also disables some useful things like being able to nfs mount, and
# things that are already namespaced with ns_capable() kernel checks, like
# hostname(1).
#
# Some of these don't apply in Slackware but are here for future reference.
#
# lxc.cap.drop = sys_admin # breaks systemd
# lxc.cap.drop = net_raw # breaks dhcp/ping
# lxc.cap.drop = setgid # breaks login (initgroups/setgroups)
# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd)
# lxc.cap.drop = setuid # breaks sshd,nfs statd
# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed)
# lxc.cap.drop = audit_write
# lxc.cap.drop = setpcap # breaks journald
# lxc.cap.drop = sys_resource # breaks systemd
#
lxc.cap.drop = mknod setfcap setpcap

View File

@ -0,0 +1,2 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -0,0 +1,20 @@
# This derives from the global common config
lxc.include = @LXCTEMPLATECONFIG@/common.conf
# Capabilities
# Uncomment these if you don't run anything that needs the capability, and
# would like the container to run with less privilege.
#
# Dropping sys_admin disables container root from doing a lot of things
# that could be bad like re-mounting lxc fstab entries rw for example,
# but also disables some useful things like being able to nfs mount, and
# things that are already namespaced with ns_capable() kernel checks, like
# hostname(1).
# lxc.cap.drop = sys_admin
# lxc.cap.drop = net_raw # breaks dhcp/ping
# lxc.cap.drop = setgid # breaks login (initgroups/setgroups)
# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd)
# lxc.cap.drop = setuid # breaks sshd,nfs statd
# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed)
# lxc.cap.drop = audit_write
lxc.cap.drop = sys_nice sys_pacct sys_rawio

View File

@ -0,0 +1,2 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf

View File

@ -0,0 +1,4 @@
# This derives from the main Ubuntu config
lxc.include = @LXCTEMPLATECONFIG@/ubuntu.common.conf
lxc.hook.clone = @LXCHOOKDIR@/ubuntu-cloud-prep

View File

@ -0,0 +1,2 @@
# This derives from the main Ubuntu lucid config
lxc.include = @LXCTEMPLATECONFIG@/ubuntu.lucid.conf

View File

@ -0,0 +1,2 @@
# This derives from the main Ubuntu userns config
lxc.include = @LXCTEMPLATECONFIG@/ubuntu.userns.conf

View File

@ -0,0 +1,35 @@
# This derives from the global common config
lxc.include = @LXCTEMPLATECONFIG@/common.conf
# Default mount entries
lxc.mount.entry = /sys/kernel/debug sys/kernel/debug none bind,optional 0 0
lxc.mount.entry = /sys/kernel/security sys/kernel/security none bind,optional 0 0
lxc.mount.entry = /sys/fs/pstore sys/fs/pstore none bind,optional 0 0
lxc.mount.entry = mqueue dev/mqueue mqueue rw,relatime,create=dir,optional 0 0
# When using LXC with apparmor, the container will be confined by default.
# If you wish for it to instead run unconfined, copy the following line
# (uncommented) to the container's configuration file.
#lxc.apparmor.profile = unconfined
# Uncomment the following line to autodetect squid-deb-proxy configuration on the
# host and forward it to the guest at start time.
#lxc.hook.pre-start = /usr/share/lxc/hooks/squid-deb-proxy-client
# If you wish to allow mounting block filesystems, then use the following
# line instead, and make sure to grant access to the block device and/or loop
# devices below in lxc.cgroup.devices.allow.
#lxc.apparmor.profile = lxc-container-default-with-mounting
# Extra cgroup device access
## rtc
lxc.cgroup.devices.allow = c 254:0 rm
## tun
lxc.cgroup.devices.allow = c 10:200 rwm
## hpet
lxc.cgroup.devices.allow = c 10:228 rwm
## kvm
lxc.cgroup.devices.allow = c 10:232 rwm
## To use loop devices, copy the following line to the container's
## configuration file (uncommented).
#lxc.cgroup.devices.allow = b 7:* rwm

View File

@ -0,0 +1,2 @@
# Ubuntu 10.04 LTS doesn't have /dev/lxc/
lxc.tty.dir =

View File

@ -0,0 +1,6 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
# Extra fstab entries as mountall can't mount those by itself
lxc.mount.entry = /sys/firmware/efi/efivars sys/firmware/efi/efivars none bind,optional 0 0
lxc.mount.entry = /proc/sys/fs/binfmt_misc proc/sys/fs/binfmt_misc none bind,optional 0 0

View File

@ -0,0 +1,35 @@
# This derives from the global common config
lxc.include = @LXCTEMPLATECONFIG@/common.conf
# Allow for 6 tty devices by default
lxc.tty.max = 6
# Set $VIRTUALIZATION so runit doesn't try to mount filesystems or start udevd
lxc.environment=VIRTUALIZATION=lxc
# Set the halt/stop signals
lxc.signal.halt=SIGCONT
# Uncomment to disable creating tty devices subdirectory in /dev
# lxc.tty.dir =
# Capabilities
# Uncomment these if you don't run anything that needs the capability, and
# would like the container to run with less privilege.
#
# Dropping sys_admin disables container root from doing a lot of things
# that could be bad like re-mounting lxc fstab entries rw for example,
# but also disables some useful things like being able to nfs mount, and
# things that are already namespaced with ns_capable() kernel checks, like
# hostname(1).
# lxc.cap.drop = sys_admin
# lxc.cap.drop = net_raw # breaks dhcp/ping
# lxc.cap.drop = setgid # breaks login (initgroups/setgroups)
# lxc.cap.drop = dac_read_search # breaks login (pam unix_chkpwd)
# lxc.cap.drop = setuid # breaks sshd,nfs statd
# lxc.cap.drop = audit_control # breaks sshd (set_loginuid failed)
# lxc.cap.drop = audit_write
# lxc.cap.drop = setpcap # big big login delays in Fedora 20 systemd
#
lxc.cap.drop = setfcap sys_nice sys_pacct sys_rawio

View File

@ -0,0 +1,8 @@
# This derives from the global userns config
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
# Set $VIRTUALIZATION so runit doesn't try to mount filesystems or start udevd
lxc.environment=VIRTUALIZATION=lxc
# Set the halt/stop signals
lxc.signal.halt=SIGCONT

222
configure.ac Normal file
View File

@ -0,0 +1,222 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_INIT([lxc-templates], [1.0.0])
AM_INIT_AUTOMAKE
# We need pkg-config
PKG_PROG_PKG_CONFIG
AC_CONFIG_SRCDIR([configure.ac])
# AC_CONFIG_AUX_DIR([config])
# AC_CONFIG_HEADERS([src/config.h])
# AM_INIT_AUTOMAKE([-Wall -Werror -Wno-portability subdir-objects])
AC_CANONICAL_HOST
# AM_PROG_CC_C_O
AC_GNU_SOURCE
# Detect the distribution. This is used for the default configuration and
# for some distro-specific build options.
AC_MSG_CHECKING([host distribution])
AC_ARG_WITH(distro, AS_HELP_STRING([--with-distro=DISTRO], [Specify the Linux distribution to target: One of redhat, oracle, centos, fedora, suse, gentoo, debian, arch, slackware, plamo, paldo, openmandriva, pardus, sparclinux, altlinux.]))
if type lsb_release >/dev/null 2>&1 && test "z$with_distro" = "z"; then
with_distro=`lsb_release -is`
fi
if test "z$with_distro" = "z"; then
AC_CHECK_FILE(/etc/redhat-release,with_distro="redhat")
AC_CHECK_FILE(/etc/oracle-release,with_distro="oracle")
AC_CHECK_FILE(/etc/sparclinux-release,with_distro="sparclinux")
AC_CHECK_FILE(/etc/centos-release,with_distro="centos")
AC_CHECK_FILE(/etc/fedora-release,with_distro="fedora")
AC_CHECK_FILE(/etc/SuSE-release,with_distro="suse")
AC_CHECK_FILE(/etc/gentoo-release,with_distro="gentoo")
AC_CHECK_FILE(/etc/debian_version,with_distro="debian")
AC_CHECK_FILE(/etc/arch-release,with_distro="arch")
AC_CHECK_FILE(/etc/slackware-version,with_distro="slackware")
AC_CHECK_FILE(/etc/plamo-version,with_distro="plamo")
AC_CHECK_FILE(/etc/frugalware-release,with_distro="frugalware")
AC_CHECK_FILE(/etc/mandrakelinux-release, with_distro="openmandriva")
AC_CHECK_FILE(/etc/mandriva-release,with_distro="openmandriva")
AC_CHECK_FILE(/etc/pardus-release,with_distro="pardus")
AC_CHECK_FILE(/etc/altlinux-release,with_distro="altlinux")
AC_CHECK_FILE(/etc/pld-release,with_distro="pld")
fi
with_distro=`echo ${with_distro} | tr '[[:upper:]]' '[[:lower:]]'`
if test "z$with_distro" = "zforsparc"; then
with_distro="sparclinux"
fi
if test "z$with_distro" = "z"; then
with_distro="unknown"
fi
case $with_distro in
ubuntu|raspbian)
distrosysconf="$sysconfdir/default"
;;
redhat|centos|fedora|oracle|oracleserver|sparclinux|altlinux|suse|opensuse*|plamo|pld)
distrosysconf="$sysconfdir/sysconfig"
;;
*)
distrosysconf="$sysconfdir/default"
;;
esac
AC_MSG_RESULT([$with_distro])
AM_CONDITIONAL([HAVE_DEBIAN], [test x"$with_distro" = "xdebian" -o x"$with_distro" = "xubuntu" -o x"$with_distro" = "xraspbian"])
AM_CONDITIONAL([DISTRO_UBUNTU], [test "x$with_distro" = "xubuntu"])
AC_CONFIG_LINKS([config/etc/default.conf:config/etc/${distroconf}])
# Not in older autoconf versions
# AS_VAR_COPY(DEST, SOURCE)
# -------------------------
# Set the polymorphic shell variable DEST to the contents of the polymorphic
# shell variable SOURCE.
m4_ifdef([AS_VAR_COPY], [],
[AC_DEFUN([AS_VAR_COPY],
[AS_LITERAL_IF([$1[]$2], [$1=$$2], [eval $1=\$$2])])
])
dnl PKG_CHECK_VAR was introduced with pkg-config 0.28
m4_ifdef([PKG_CHECK_VAR], [],
[AC_DEFUN([PKG_CHECK_VAR],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])dnl
])# PKG_CHECK_VAR
])
# Allow overriding the default runtime dir (/run)
AC_ARG_WITH([runtime-path],
[AC_HELP_STRING(
[--with-runtime-path=dir],
[runtime directory (default: /run)]
)], [], [with_runtime_path=['/run']])
# LXC container path, where the containers are actually stored
# This is overridden by an entry in the file called LXCCONF
# (i.e. /etc/lxc/lxc.conf)
AC_ARG_WITH([config-path],
[AC_HELP_STRING(
[--with-config-path=dir],
[lxc configuration repository path]
)], [], [with_config_path=['${localstatedir}/lib/lxc']])
# The path of the global lxc configuration file.
AC_ARG_WITH([global-conf],
[AC_HELP_STRING(
[--with-global-conf=dir],
[global lxc configuration file]
)], [], [with_global_conf=['${sysconfdir}/lxc/lxc.conf']])
# Rootfs path, where the container mount structure is assembled
AC_ARG_WITH([rootfs-path],
[AC_HELP_STRING(
[--with-rootfs-path=dir],
[lxc rootfs mount point]
)], [], [with_rootfs_path=['${libdir}/lxc/rootfs']])
# Expand some useful variables
AS_AC_EXPAND(PREFIX, "$prefix")
AS_AC_EXPAND(LIBDIR, "$libdir")
AS_AC_EXPAND(BINDIR, "$bindir")
AS_AC_EXPAND(SBINDIR, "$sbindir")
AS_AC_EXPAND(LIBEXECDIR, "$libexecdir")
AS_AC_EXPAND(INCLUDEDIR, "$includedir")
AS_AC_EXPAND(SYSCONFDIR, "$sysconfdir")
AS_AC_EXPAND(LXC_DEFAULT_CONFIG, "$sysconfdir/lxc/default.conf")
AS_AC_EXPAND(DATADIR, "$datadir")
AS_AC_EXPAND(LOCALSTATEDIR, "$localstatedir")
AS_AC_EXPAND(LXC_GENERATE_DATE, "$(date --utc --date=@${SOURCE_DATE_EPOCH:-$(date +%s)} '+%Y-%m-%d')")
AS_AC_EXPAND(LXCPATH, "$with_config_path")
AS_AC_EXPAND(LXC_GLOBAL_CONF, "$with_global_conf")
AS_AC_EXPAND(LXC_USERNIC_CONF, "$with_usernic_conf")
AS_AC_EXPAND(LXC_USERNIC_DB, "$with_usernic_db")
AS_AC_EXPAND(LXC_DISTRO_SYSCONF, "$distrosysconf")
AS_AC_EXPAND(LXCROOTFSMOUNT, "$with_rootfs_path")
AS_AC_EXPAND(LXCTEMPLATEDIR, "$datadir/lxc/templates")
AS_AC_EXPAND(LXCTEMPLATECONFIG, "$datadir/lxc/config")
AS_AC_EXPAND(LXCHOOKDIR, "$datadir/lxc/hooks")
AS_AC_EXPAND(LXCBINHOOKDIR, "$libexecdir/lxc/hooks")
AS_AC_EXPAND(LXCINITDIR, "$libexecdir")
AS_AC_EXPAND(RUNTIME_PATH, "$with_runtime_path")
# Check for some standard binaries
AC_PROG_SED
# Files requiring some variable expansion
AC_CONFIG_FILES([
Makefile
config/Makefile
config/alpine.common.conf
config/alpine.userns.conf
config/archlinux.common.conf
config/archlinux.userns.conf
config/centos.common.conf
config/centos.userns.conf
config/debian.common.conf
config/debian.userns.conf
config/fedora.common.conf
config/fedora.userns.conf
config/gentoo.common.conf
config/gentoo.moresecure.conf
config/gentoo.userns.conf
config/opensuse.common.conf
config/opensuse.userns.conf
config/oracle.common.conf
config/oracle.userns.conf
config/plamo.common.conf
config/plamo.userns.conf
config/slackware.common.conf
config/slackware.userns.conf
config/ubuntu-cloud.common.conf
config/ubuntu-cloud.lucid.conf
config/ubuntu-cloud.userns.conf
config/ubuntu.common.conf
config/ubuntu.lucid.conf
config/ubuntu.userns.conf
config/openwrt.common.conf
config/sparclinux.common.conf
config/sparclinux.userns.conf
config/voidlinux.common.conf
config/voidlinux.userns.conf
config/sabayon.common.conf
config/sabayon.userns.conf
templates/Makefile
templates/lxc-alpine
templates/lxc-altlinux
templates/lxc-archlinux
templates/lxc-busybox
templates/lxc-centos
templates/lxc-cirros
templates/lxc-debian
templates/lxc-fedora
templates/lxc-fedora-legacy
templates/lxc-gentoo
templates/lxc-openmandriva
templates/lxc-opensuse
templates/lxc-oracle
templates/lxc-plamo
templates/lxc-pld
templates/lxc-slackware
templates/lxc-sshd
templates/lxc-ubuntu
templates/lxc-ubuntu-cloud
templates/lxc-sparclinux
templates/lxc-voidlinux
templates/lxc-sabayon
])
AC_CONFIG_COMMANDS([default],[[]],[[]])
AC_OUTPUT
# Configuration overview
cat << EOF
----------------------------
Environment:
- distribution: $with_distro
EOF

25
templates/Makefile.am Normal file
View File

@ -0,0 +1,25 @@
templatesdir=@LXCTEMPLATEDIR@
templates_SCRIPTS = \
lxc-alpine \
lxc-altlinux \
lxc-archlinux \
lxc-busybox \
lxc-centos \
lxc-cirros \
lxc-debian \
lxc-fedora \
lxc-fedora-legacy \
lxc-gentoo \
lxc-openmandriva \
lxc-opensuse \
lxc-oracle \
lxc-plamo \
lxc-pld \
lxc-slackware \
lxc-sshd \
lxc-ubuntu \
lxc-ubuntu-cloud \
lxc-sparclinux \
lxc-voidlinux \
lxc-sabayon

516
templates/lxc-alpine.in Normal file
View File

@ -0,0 +1,516 @@
#!/bin/sh
# vim: set ts=4:
# Exit on error and treat unset variables as an error.
set -eu
#
# LXC template for Alpine Linux 3+
#
# Note: Do not replace tabs with spaces, it would break heredocs!
# Authors:
# Jakub Jirutka <jakub@jirutka.cz>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#=========================== Constants ============================#
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
readonly LOCAL_STATE_DIR='@LOCALSTATEDIR@'
readonly LXC_TEMPLATE_CONFIG='@LXCTEMPLATECONFIG@'
readonly LXC_CACHE_DIR="${LXC_CACHE_PATH:-"$LOCAL_STATE_DIR/cache/lxc"}/alpine"
# SHA256 checksums of GPG keys for APK.
readonly APK_KEYS_SHA256="\
9c102bcc376af1498d549b77bdbfa815ae86faa1d2d82f040e616b18ef2df2d4 alpine-devel@lists.alpinelinux.org-4a6a0840.rsa.pub
2adcf7ce224f476330b5360ca5edb92fd0bf91c92d83292ed028d7c4e26333ab alpine-devel@lists.alpinelinux.org-4d07755e.rsa.pub
ebf31683b56410ecc4c00acd9f6e2839e237a3b62b5ae7ef686705c7ba0396a9 alpine-devel@lists.alpinelinux.org-5243ef4b.rsa.pub
1bb2a846c0ea4ca9d0e7862f970863857fc33c32f5506098c636a62a726a847b alpine-devel@lists.alpinelinux.org-524d27bb.rsa.pub
12f899e55a7691225603d6fb3324940fc51cd7f133e7ead788663c2b7eecb00c alpine-devel@lists.alpinelinux.org-5261cecb.rsa.pub
73867d92083f2f8ab899a26ccda7ef63dfaa0032a938620eda605558958a8041 alpine-devel@lists.alpinelinux.org-58199dcc.rsa.pub
9a4cd858d9710963848e6d5f555325dc199d1c952b01cf6e64da2c15deedbd97 alpine-devel@lists.alpinelinux.org-58cbb476.rsa.pub
780b3ed41786772cbc7b68136546fa3f897f28a23b30c72dde6225319c44cfff alpine-devel@lists.alpinelinux.org-58e4f17d.rsa.pub"
readonly APK_KEYS_URI='http://alpinelinux.org/keys'
readonly DEFAULT_MIRROR_URL='http://dl-cdn.alpinelinux.org/alpine'
: ${APK_KEYS_DIR:=/etc/apk/keys}
if ! ls "$APK_KEYS_DIR"/alpine* >/dev/null 2>&1; then
APK_KEYS_DIR="$LXC_CACHE_DIR/bootstrap/keys"
fi
readonly APK_KEYS_DIR
: ${APK:=$(command -v apk || true)}
if [ ! -x "$APK" ]; then
APK="$LXC_CACHE_DIR/bootstrap/sbin/apk.static"
fi
readonly APK
#======================== Helper Functions ========================#
usage() {
cat <<-EOF
Template specific options can be passed to lxc-create after a '--' like this:
lxc-create --name=NAME [lxc-create-options] -- [template-options] [PKG...]
PKG Additional APK package(s) to install into the container.
Template options:
-a ARCH, --arch=ARCH The container architecture (e.g. x86, x86_64); defaults
to the host arch.
-d, --debug Run this script in a debug mode (set -x and wget w/o -q).
-F, --flush-cache Remove cached files before build.
-m URL --mirror=URL The Alpine mirror to use; defaults to $DEFAULT_MIRROR_URL.
-r VER, --release=VER The Alpine release branch to install; default is the
latest stable.
Environment variables:
APK The apk-tools binary to use when building rootfs. If not set
or not executable and apk is not on PATH, then the script
will download the latest apk-tools-static.
APK_KEYS_DIR Path to directory with GPG keys for APK. If not set and
/etc/apk/keys does not contain alpine keys, then the script
will download the keys from ${APK_KEYS_URI}.
LXC_CACHE_PATH Path to the cache directory where to store bootstrap files
and APK packages.
EOF
}
die() {
local retval=$1; shift
printf 'ERROR: %s\n' "$@" 1>&2
exit $retval
}
einfo() {
printf "\n==> $1\n"
}
fetch() {
if [ "$DEBUG" = 'yes' ]; then
wget -T 10 -O - $@
else
wget -T 10 -O - -q $@
fi
}
latest_release_branch() {
local arch="$1"
local branch=$(fetch "$MIRROR_URL/latest-stable/releases/$arch/latest-releases.yaml" \
| sed -En 's/^[ \t]*branch: (.*)$/\1/p' \
| head -n 1)
[ -n "$branch" ] && echo "$branch"
}
parse_arch() {
case "$1" in
x86 | i[3-6]86) echo 'x86';;
x86_64 | amd64) echo 'x86_64';;
aarch64 | arm64) echo 'aarch64';;
armv7) echo 'armv7';;
arm*) echo 'armhf';;
ppc64le) echo 'ppc64le';;
*) return 1;;
esac
}
run_exclusively() {
local lock_name="$1"
local timeout=$2
shift 2
mkdir -p "$LOCAL_STATE_DIR/lock/subsys"
local retval
{
echo -n "Obtaining an exclusive lock..."
if ! flock -x 9; then
echo ' failed.'
return 1
fi
echo ' done'
"$@"; retval=$?
} 9> "$LOCAL_STATE_DIR/lock/subsys/lxc-alpine-$lock_name"
return $retval
}
#============================ Bootstrap ===========================#
bootstrap() {
if [ "$FLUSH_CACHE" = 'yes' ] && [ -d "$LXC_CACHE_DIR/bootstrap" ]; then
einfo 'Cleaning cached bootstrap files'
rm -Rf "$LXC_CACHE_DIR/bootstrap"
fi
einfo 'Fetching and/or verifying APK keys'
fetch_apk_keys "$APK_KEYS_DIR"
if [ ! -x "$APK" ]; then
einfo 'Fetching apk-tools static binary'
local host_arch=$(parse_arch $(uname -m))
fetch_apk_static "$LXC_CACHE_DIR/bootstrap" "$host_arch"
fi
}
fetch_apk_keys() {
local dest="$1"
local line keyname
mkdir -p "$dest"
cd "$dest"
echo "$APK_KEYS_SHA256" | while read -r line; do
keyname="${line##* }"
if [ ! -s "$keyname" ]; then
fetch "$APK_KEYS_URI/$keyname" > "$keyname"
fi
echo "$line" | sha256sum -c -
done || exit 2
cd - >/dev/null
}
fetch_apk_static() {
local dest="$1"
local arch="$2"
local pkg_name='apk-tools-static'
mkdir -p "$dest"
local pkg_ver=$(fetch "$MIRROR_URL/latest-stable/main/$arch/APKINDEX.tar.gz" \
| tar -xzO APKINDEX \
| sed -n "/P:${pkg_name}/,/^$/ s/V:\(.*\)$/\1/p")
[ -n "$pkg_ver" ] || die 2 "Cannot find a version of $pkg_name in APKINDEX"
fetch "$MIRROR_URL/latest-stable/main/$arch/${pkg_name}-${pkg_ver}.apk" \
| tar -xz -C "$dest" sbin/ # --extract --gzip --directory
[ -s "$dest/sbin/apk.static" ] || die 2 'apk.static not found'
local keyname=$(echo "$dest"/sbin/apk.static.*.pub | sed 's/.*\.SIGN\.RSA\.//')
openssl dgst -sha1 \
-verify "$APK_KEYS_DIR/$keyname" \
-signature "$dest/sbin/apk.static.SIGN.RSA.$keyname" \
"$dest/sbin/apk.static" \
|| die 2 'Signature verification for apk.static failed'
# Note: apk doesn't return 0 for --version
local out="$("$dest"/sbin/apk.static --version)"
echo "$out"
[ "${out%% *}" = 'apk-tools' ] || die 3 'apk.static --version failed'
}
#============================ Install ============================#
install() {
local dest="$1"
local arch="$2"
local branch="$3"
local extra_packages="$4"
local apk_cache="$LXC_CACHE_DIR/apk/$arch"
if [ "$FLUSH_CACHE" = 'yes' ] && [ -d "$apk_cache" ]; then
einfo "Cleaning cached APK packages for $arch"
rm -Rf "$apk_cache"
fi
mkdir -p "$apk_cache"
einfo "Installing Alpine Linux in $dest"
cd "$dest"
mkdir -p etc/apk
ln -s "$apk_cache" etc/apk/cache
local repo; for repo in main community; do
echo "$MIRROR_URL/$branch/$repo" >> etc/apk/repositories
done
install_packages "$arch" "alpine-base $extra_packages"
make_dev_nodes
setup_inittab
setup_hosts
setup_network
setup_services
chroot . /bin/true \
|| die 3 'Failed to execute /bin/true in chroot, the builded rootfs is broken!'
rm etc/apk/cache
cd - >/dev/null
}
install_packages() {
local arch="$1"
local packages="$2"
$APK --arch="$arch" --root=. --keys-dir="$APK_KEYS_DIR" \
--update-cache --initdb add $packages
}
make_dev_nodes() {
mkdir -p -m 755 dev/pts
mkdir -p -m 1777 dev/shm
mknod -m 666 dev/zero c 1 5
mknod -m 666 dev/full c 1 7
mknod -m 666 dev/random c 1 8
mknod -m 666 dev/urandom c 1 9
local i; for i in $(seq 0 4); do
mknod -m 620 dev/tty$i c 4 $i
chown 0:5 dev/tty$i # root:tty
done
mknod -m 666 dev/tty c 5 0
chown 0:5 dev/tty # root:tty
mknod -m 620 dev/console c 5 1
mknod -m 666 dev/ptmx c 5 2
chown 0:5 dev/ptmx # root:tty
}
setup_inittab() {
# Remove unwanted ttys.
sed -i '/^tty[5-9]\:\:.*$/d' etc/inittab
cat <<-EOF >> etc/inittab
# Main LXC console console
::respawn:/sbin/getty 38400 console
EOF
}
setup_hosts() {
# This runscript injects localhost entries with the current hostname
# into /etc/hosts.
cat <<'EOF' > etc/init.d/hosts
#!/sbin/openrc-run
start() {
local start_tag='# begin generated'
local end_tag='# end generated'
local content=$(
cat <<-EOF
$start_tag by /etc/init.d/hosts
127.0.0.1 $(hostname).local $(hostname) localhost
::1 $(hostname).local $(hostname) localhost
$end_tag
EOF
)
if grep -q "^${start_tag}" /etc/hosts; then
# escape \n, busybox sed doesn't like them
content=${content//$'\n'/\\$'\n'}
sed -ni "/^${start_tag}/ {
a\\${content}
# read and discard next line and repeat until $end_tag or EOF
:a; n; /^${end_tag}/!ba; n
}; p" /etc/hosts
else
printf "$content" >> /etc/hosts
fi
}
EOF
chmod +x etc/init.d/hosts
# Wipe it, will be generated by the above runscript.
echo -n > etc/hosts
}
setup_network() {
# Note: loopback is automatically started by LXC.
cat <<-EOF > etc/network/interfaces
auto eth0
iface eth0 inet dhcp
hostname \$(hostname)
EOF
}
setup_services() {
local svc_name
# Specify the LXC subsystem.
sed -i 's/^#*rc_sys=.*/rc_sys="lxc"/' etc/rc.conf
# boot runlevel
for svc_name in bootmisc hosts syslog; do
ln -s /etc/init.d/$svc_name etc/runlevels/boot/$svc_name
done
# default runlevel
for svc_name in networking cron crond; do
# issue 1164: alpine renamed cron to crond
# Use the one that exists.
if [ -e etc/init.d/$svc_name ]; then
ln -s /etc/init.d/$svc_name etc/runlevels/default/$svc_name
fi
done
}
#=========================== Configure ===========================#
configure_container() {
local config="$1"
local hostname="$2"
local arch="$3"
cat <<-EOF >> "$config"
# Specify container architecture.
lxc.arch = $arch
# Set hostname.
lxc.uts.name = $hostname
# If something doesn't work, try to comment this out.
# Dropping sys_admin disables container root from doing a lot of things
# that could be bad like re-mounting lxc fstab entries rw for example,
# but also disables some useful things like being able to nfs mount, and
# things that are already namespaced with ns_capable() kernel checks, like
# hostname(1).
lxc.cap.drop = sys_admin
# Comment this out if you have to debug processes by tracing.
lxc.cap.drop = sys_ptrace
# Include common configuration.
lxc.include = $LXC_TEMPLATE_CONFIG/alpine.common.conf
EOF
}
#============================= Main ==============================#
if [ "$(id -u)" != "0" ]; then
die 1 "This script must be run as 'root'"
fi
# Parse command options.
options=$(getopt -o a:dFm:n:p:r:h -l arch:,debug,flush-cache,mirror:,name:,\
path:,release:,rootfs:,help,mapped-uid:,mapped-gid: -- "$@")
eval set -- "$options"
# Clean variables and set defaults.
arch="$(uname -m)"
debug='no'
flush_cache='no'
mirror_url=
name=
path=
release=
rootfs=
# Process command options.
while [ $# -gt 0 ]; do
case $1 in
-a | --arch)
arch=$2; shift 2
;;
-d | --debug)
debug='yes'; shift 1
;;
-F | --flush-cache)
flush_cache='yes'; shift 1
;;
-m | --mirror)
mirror_url=$2; shift 2
;;
-n | --name)
name=$2; shift 2
;;
-p | --path)
path=$2; shift 2
;;
-r | --release)
release=$2; shift 2
;;
--rootfs)
rootfs=$2; shift 2
;;
-h | --help)
usage; exit 0
;;
--)
shift; break
;;
--mapped-[ug]id)
die 1 "This template can't be used for unprivileged containers." \
'You may want to try the "download" template instead.'
;;
*)
echo "Unknown option: $1" 1>&2
usage; exit 1
;;
esac
done
extra_packages="$@"
[ "$debug" = 'yes' ] && set -x
# Set global variables.
readonly DEBUG="$debug"
readonly FLUSH_CACHE="$flush_cache"
readonly MIRROR_URL="${mirror_url:-$DEFAULT_MIRROR_URL}"
# Validate options.
[ -n "$name" ] || die 1 'Missing required option --name'
[ -n "$path" ] || die 1 'Missing required option --path'
if [ -z "$rootfs" ] && [ -f "$path/config" ]; then
rootfs="$(sed -nE 's/^lxc.rootfs.path\s*=\s*(.*)$/\1/p' "$path/config")"
fi
if [ -z "$rootfs" ]; then
rootfs="$path/rootfs"
fi
arch=$(parse_arch "$arch") \
|| die 1 "Unsupported architecture: $arch"
if [ -z "$release" ]; then
release=$(latest_release_branch "$arch") \
|| die 2 'Failed to resolve Alpine last release branch'
fi
# Here we go!
run_exclusively 'bootstrap' 10 bootstrap
run_exclusively "$arch" 30 install "$rootfs" "$arch" "$release" "$extra_packages"
configure_container "$path/config" "$name" "$arch"
einfo "Container's rootfs and config have been created"
cat <<-EOF
Edit the config file $path/config to check/enable networking setup.
The installed system is preconfigured for a loopback and single network
interface configured via DHCP.
To start the container, run "lxc-start -n $name".
The root password is not set; to enter the container run "lxc-attach -n $name".
EOF

498
templates/lxc-altlinux.in Normal file
View File

@ -0,0 +1,498 @@
#!/bin/bash
#
# template script for generating altlinux container for LXC
#
#
# lxc: linux Container library
# Authors:
# Alexey Shabalin <shaba@altlinux.org>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# Detect use under userns (unsupported)
for arg in "$@"; do
[ "$arg" = "--" ] && break
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
echo "This template can't be used for unprivileged containers." 1>&2
echo "You may want to try the \"download\" template instead." 1>&2
exit 1
fi
done
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
#Configurations
arch=$(uname -m)
cache_base=@LOCALSTATEDIR@/cache/lxc/altlinux/$arch
default_path=@LXCPATH@
default_profile=default
profile_dir=/etc/lxc/profiles
lxc_network_type=veth
lxc_network_link=virbr0
# is this altlinux?
[ -f /etc/altlinux-release ] && is_altlinux=true
configure_altlinux()
{
# disable selinux in altlinux
mkdir -p $rootfs_path/selinux
echo 0 > $rootfs_path/selinux/enforce
mkdir -p ${rootfs_path}/etc/net/ifaces/eth0
cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/options
BOOTPROTO=${BOOTPROTO}
ONBOOT=yes
NM_CONTROLLED=yes
TYPE=eth
EOF
if [ ${BOOTPROTO} != "dhcp" ]; then
# ip address
cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/ipv4address
${ipv4}
EOF
cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/ipv4route
${gw}
EOF
cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/resolv.conf
nameserver ${dns}
EOF
cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/ipv6address
${ipv6}
EOF
cat <<EOF > ${rootfs_path}/etc/net/ifaces/eth0/ipv6route
${gw6}
EOF
fi
# set the hostname
cat <<EOF > ${rootfs_path}/etc/sysconfig/network
NETWORKING=yes
CONFMETHOD=etcnet
HOSTNAME=${UTSNAME}
RESOLV_MODS=yes
EOF
# set minimal hosts
cat <<EOF > $rootfs_path/etc/hosts
127.0.0.1 localhost.localdomain localhost $name
EOF
# Allow to login at virsh console. loginuid.so doen't work in the absence of auditd.
# sed -i 's/^.*loginuid.so.*$/\#&/' ${rootfs_path}/etc/pam.d/common-login
# Allow root to login at virsh console
echo "pts/0" >> ${rootfs_path}/etc/securetty
echo "console" >> ${rootfs_path}/etc/securetty
# Enable services
for service in network syslogd random NetworkManager
do
chroot ${rootfs_path} chkconfig $service --list &>/dev/null && chroot ${rootfs_path} chkconfig $service on || true
# For systemd
chroot ${rootfs_path} systemctl -q enable $service &>/dev/null|| true
done
# Disable services
for service in rawdevices fbsetfont
do
chroot ${rootfs_path} chkconfig $service --list &>/dev/null && chroot ${rootfs_path} chkconfig $service off || true
chroot ${rootfs_path} systemctl -q disable $service &>/dev/null || true
done
subst 's/^\([3-9]\+:[0-9]\+:respawn:\/sbin\/mingetty.*\)/#\1/' ${rootfs_path}/etc/inittab
echo "c1:2345:respawn:/sbin/mingetty --noclear console" >> ${rootfs_path}/etc/inittab
[ -f "${rootfs_path}/etc/syslog.conf" ] && \
subst 's,\/dev\/tty12,/var/log/syslog/console,' ${rootfs_path}/etc/syslog.conf
dev_path="${rootfs_path}/dev"
rm -rf ${dev_path}
mkdir -p ${dev_path}
mknod -m 666 ${dev_path}/null c 1 3
mknod -m 666 ${dev_path}/zero c 1 5
mknod -m 644 ${dev_path}/random c 1 8
mknod -m 644 ${dev_path}/urandom c 1 9
mkdir -m 755 ${dev_path}/pts
mkdir -m 1777 ${dev_path}/shm
mknod -m 666 ${dev_path}/tty c 5 0
chown root:tty ${dev_path}/tty
mknod -m 600 ${dev_path}/tty0 c 4 0
mknod -m 600 ${dev_path}/tty1 c 4 1
mknod -m 600 ${dev_path}/tty2 c 4 2
mknod -m 600 ${dev_path}/tty3 c 4 3
mknod -m 600 ${dev_path}/tty4 c 4 4
mknod -m 600 ${dev_path}/console c 5 1
mknod -m 666 ${dev_path}/full c 1 7
mknod -m 600 ${dev_path}/initctl p
mknod -m 666 ${dev_path}/ptmx c 5 2
chown root:tty ${dev_path}/ptmx
ln -s /proc/self/fd ${dev_path}/fd
ln -s /proc/kcore ${dev_path}/core
mkdir -m 755 ${dev_path}/mapper
mknod -m 600 ${dev_path}/mapper/control c 10 236
mkdir -m 755 ${dev_path}/net
mknod -m 666 ${dev_path}/net/tun c 10 200
if [ -n "${root_password}" ]; then
echo "setting root passwd to $root_password"
echo "root:$root_password" | chroot $rootfs_path chpasswd
fi
return 0
}
download_altlinux()
{
if [ -z "$aptconfver" ]; then
case "$release" in
sisyphus)
aptconfver=apt-conf-sisyphus ;;
*)
aptconfver=apt-conf-branch ;;
esac
fi
# check the mini altlinux was not already downloaded
INSTALL_ROOT=$cache/partial
mkdir -p $INSTALL_ROOT
if [ $? -ne 0 ]; then
echo "Failed to create '$INSTALL_ROOT' directory"
return 1
fi
# download a mini altlinux into a cache
echo "Downloading altlinux minimal ..."
APT_GET="apt-get -o RPM::RootDir=$INSTALL_ROOT -y"
PKG_LIST="$(grep -hs '^[^#]' "$profile_dir/$profile")"
# if no configuration file $profile -- fall back to default list of packages
[ -z "$PKG_LIST" ] && PKG_LIST="interactivesystem apt $aptconfver etcnet-full openssh-server systemd-sysvinit systemd-units systemd NetworkManager-daemon"
mkdir -p $INSTALL_ROOT/var/lib/rpm
rpm --root $INSTALL_ROOT --initdb
# some scripts want to have /dev/null at least
dev_path="$INSTALL_ROOT/dev"
if [ ! -c "${dev_path}/null" ]; then
mkdir -p "${dev_path}"
mknod -m 666 "${dev_path}/null" c 1 3
fi
$APT_GET install $PKG_LIST
if [ $? -ne 0 ]; then
echo "Failed to download the rootfs, aborting."
return 1
fi
mv "$INSTALL_ROOT" "$cache/rootfs"
echo "Download complete."
return 0
}
copy_altlinux()
{
# make a local copy of the minialtlinux
echo -n "Copying rootfs to $rootfs_path ..."
#cp -a $cache/rootfs-$arch $rootfs_path || return 1
# i prefer rsync (no reason really)
mkdir -p $rootfs_path
rsync -SHaAX $cache/rootfs/ $rootfs_path/
return 0
}
update_altlinux()
{
chroot $cache/rootfs apt-get update
chroot $cache/rootfs apt-get -y dist-upgrade
}
install_altlinux()
{
mkdir -p @LOCALSTATEDIR@/lock/subsys/
(
flock -x 9
if [ $? -ne 0 ]; then
echo "Cache repository is busy."
return 1
fi
echo "Checking cache download in $cache/rootfs ... "
if [ ! -e "$cache/rootfs" ]; then
download_altlinux
if [ $? -ne 0 ]; then
echo "Failed to download 'altlinux base'"
return 1
fi
else
echo "Cache found. Updating..."
update_altlinux
if [ $? -ne 0 ]; then
echo "Failed to update 'altlinux base', continuing with last known good cache"
else
echo "Update finished"
fi
fi
echo "Copy $cache/rootfs to $rootfs_path ... "
copy_altlinux
if [ $? -ne 0 ]; then
echo "Failed to copy rootfs"
return 1
fi
return 0
) 9>@LOCALSTATEDIR@/lock/subsys/lxc-altlinux
return $?
}
copy_configuration()
{
mkdir -p $config_path
grep -q "^lxc.rootfs.path" $config_path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs_path" >> $config_path/config
cat <<EOF >> $config_path/config
lxc.uts.name = $name
lxc.tty.max = 4
lxc.pty.max = 1024
lxc.cap.drop = sys_module mac_admin mac_override sys_time
# When using LXC with apparmor, uncomment the next line to run unconfined:
#lxc.apparmor.profile = unconfined
#networking
#lxc.net.0.type = $lxc_network_type
#lxc.net.0.flags = up
#lxc.net.0.link = $lxc_network_link
#lxc.net.0.name = veth0
#lxc.net.0.mtu = 1500
EOF
if [ ! -z ${ipv4} ]; then
cat <<EOF >> $config_path/config
lxc.net.0.ipv4.address = $ipv4
EOF
fi
if [ ! -z ${gw} ]; then
cat <<EOF >> $config_path/config
lxc.net.0.ipv4.gateway = $gw
EOF
fi
if [ ! -z ${ipv6} ]; then
cat <<EOF >> $config_path/config
lxc.net.0.ipv6.address = $ipv6
EOF
fi
if [ ! -z ${gw6} ]; then
cat <<EOF >> $config_path/config
lxc.net.0.ipv6.gateway = $gw6
EOF
fi
cat <<EOF >> $config_path/config
#cgroups
lxc.cgroup.devices.deny = a
# /dev/null and zero
lxc.cgroup.devices.allow = c 1:3 rwm
lxc.cgroup.devices.allow = c 1:5 rwm
# consoles
lxc.cgroup.devices.allow = c 5:1 rwm
lxc.cgroup.devices.allow = c 5:0 rwm
lxc.cgroup.devices.allow = c 4:0 rwm
lxc.cgroup.devices.allow = c 4:1 rwm
# /dev/{,u}random
lxc.cgroup.devices.allow = c 1:9 rwm
lxc.cgroup.devices.allow = c 1:8 rwm
lxc.cgroup.devices.allow = c 136:* rwm
lxc.cgroup.devices.allow = c 5:2 rwm
# rtc
lxc.cgroup.devices.allow = c 10:135 rwm
lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
EOF
if [ $? -ne 0 ]; then
echo "Failed to add configuration"
return 1
fi
return 0
}
clean()
{
if [ ! -e $cache ]; then
exit 0
fi
# lock, so we won't purge while someone is creating a repository
(
flock -x 9
if [ $? != 0 ]; then
echo "Cache repository is busy."
exit 1
fi
echo -n "Purging the download cache for ALTLinux-$release..."
rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
exit 0
) 9>@LOCALSTATEDIR@/lock/subsys/lxc-altlinux
}
usage()
{
cat <<EOF
usage:
$1 -n|--name=<container_name>
[-p|--path=<path>] [-c|--clean] [-R|--release=<ALTLinux_release>]
[-4|--ipv4=<ipv4 address>] [-6|--ipv6=<ipv6 address>]
[-g|--gw=<gw address>] [-d|--dns=<dns address>]
[-P|--profile=<name of the profile>] [--rootfs=<path>]
[-a|--apt-conf=<apt-conf>]
[-A|--arch=<arch of the container>]
[-h|--help]
Mandatory args:
-n,--name container name, used to as an identifier for that container from now on
Optional args:
-p,--path path to where the container rootfs will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case
-c,--clean clean the cache
-R,--release ALTLinux release for the new container. if the host is ALTLinux, then it will defaultto the host's release.
-4,--ipv4 specify the ipv4 address to assign to the virtualized interface, eg. 192.168.1.123/24
-6,--ipv6 specify the ipv6 address to assign to the virtualized interface, eg. 2003:db8:1:0:214:1234:fe0b:3596/64
-g,--gw specify the default gw, eg. 192.168.1.1
-G,--gw6 specify the default gw, eg. 2003:db8:1:0:214:1234:fe0b:3596
-d,--dns specify the DNS server, eg. 192.168.1.2
-a,--apt-conf specify preferred 'apt-conf' package, eg. 'apt-conf-branch'
-P,--profile Profile name is the file name in /etc/lxc/profiles contained packages name for install to cache.
-A,--arch NOT USED YET. Define what arch the container will be [i686,x86_64]
---rootfs rootfs path
-h,--help print this help
EOF
return 0
}
options=$(getopt -o hp:n:P:cR:4:6:g:d:a: -l help,rootfs:,path:,name:,profile:,clean,release:,ipv4:,ipv6:,gw:,dns:,apt-conf: -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
fi
eval set -- "$options"
while true
do
case "$1" in
-h|--help) usage $0 && exit 0;;
-p|--path) path=$2; shift 2;;
--rootfs) rootfs_path=$2; shift 2;;
-n|--name) name=$2; shift 2;;
-P|--profile) profile=$2; shift 2;;
-c|--clean) clean=1; shift 1;;
-R|--release) release=$2; shift 2;;
-4|--ipv4) ipv4=$2; shift 2;;
-6|--ipv6) ipv6=$2; shift 2;;
-g|--gw) gw=$2; shift 2;;
-d|--dns) dns=$2; shift 2;;
-a|--apt-conf) aptconfver=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
if [ ! -z "$clean" -a -z "$path" ]; then
clean || exit 1
exit 0
fi
type apt-get >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "'apt-get' command is missing"
exit 1
fi
if [ -z "$path" ]; then
path=$default_path
fi
if [ -z "$profile" ]; then
profile=$default_profile
fi
if [ -z "$release" ]; then
if [ "$is_altlinux" ]; then
release=$(cat /etc/altlinux-release |awk '/^ALT/ {print $3}')
else
echo "This is not a ALTLinux host and release missing, use -R|--release to specify release"
exit 1
fi
fi
if [ -z "$ipv4" -a -z "$ipv6" ]; then
BOOTPROTO="dhcp"
else
BOOTPROTO="static"
fi
if [ "$(id -u)" != "0" ]; then
echo "This script should be run as 'root'"
exit 1
fi
# check for 'lxc.rootfs.path' passed in through default config by lxc-create
if [ -z "$rootfs_path" ]; then
if grep -q '^lxc.rootfs.path' $path/config 2>/dev/null ; then
rootfs_path=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config)
else
rootfs_path=$path/rootfs
fi
fi
config_path=$default_path/$name
cache=$cache_base/$release/$profile
install_altlinux
if [ $? -ne 0 ]; then
echo "failed to install altlinux"
exit 1
fi
configure_altlinux
if [ $? -ne 0 ]; then
echo "failed to configure altlinux for a container"
exit 1
fi
copy_configuration
if [ $? -ne 0 ]; then
echo "failed write configuration file"
exit 1
fi
if [ ! -z "$clean" ]; then
clean || exit 1
exit 0
fi
echo "container rootfs and config created"
echo "network configured as $lxc_network_type in the $lxc_network_link"

334
templates/lxc-archlinux.in Normal file
View File

@ -0,0 +1,334 @@
#!/bin/bash
#
# template script for generating Arch Linux container for LXC
#
#
# lxc: linux Container library
# Authors:
# Alexander Vladimirov <alexander.idkfa.vladimirov@gmail.com>
# John Lane <lxc@jelmail.com>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# Detect use under userns (unsupported)
for arg in "$@"; do
[ "$arg" = "--" ] && break
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
echo "This template can't be used for unprivileged containers." 1>&2
echo "You may want to try the \"download\" template instead." 1>&2
exit 1
fi
done
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
# defaults
arch=$(uname -m)
default_path="@LXCPATH@"
default_locale="en_US.UTF-8"
pacman_config="/etc/pacman.conf"
common_config="@LXCTEMPLATECONFIG@/common.conf"
shared_config="@LXCTEMPLATECONFIG@/archlinux.common.conf"
# by default, install 'base' except the kernel
pkg_blacklist="linux"
base_packages=()
for pkg in $(pacman -Sqg base); do
[ "${pkg_blacklist#*$pkg}" = "$pkg_blacklist" ] && base_packages+=($pkg)
done
declare -a additional_packages
# split comma-separated string into an array
# ${1} - string to split
# ${2} - separator (default is ",")
# ${result} - result value on success
split_string() {
local ifs=${IFS}
IFS="${2:-,}"
read -a result < <(echo "${1}")
IFS=${ifs}
return 0
}
[ -f /etc/arch-release ] && is_arch=true
# Arch-specific preconfiguration for container
configure_arch() {
# on ArchLinux, read defaults from host systemd configuration
if [ "${is_arch}" ]; then
cp -p /etc/locale.conf /etc/locale.gen "${rootfs_path}/etc/"
else
echo "LANG=${default_locale}" > "${rootfs_path}/etc/locale.conf"
if [ -e "${rootfs_path}/etc/locale.gen" ]; then
sed -i 's@^#\(en_US\.UTF-8\)@\1@' "${rootfs_path}/etc/locale.gen"
if [ ! "${default_locale}" = "en_US.UTF-8" ]; then
echo "${default_locale} ${default_locale##*.}" >> \
"${rootfs_path}/etc/locale.gen"
fi
fi
fi
# hostname and nameservers
echo "${name}" > "${rootfs_path}/etc/hostname"
# network configuration
cat > "${rootfs_path}/etc/systemd/network/eth0.network" << EOF
[Match]
Name=eth0
[Network]
DHCP=ipv4
EOF
# chroot and configure system
arch-chroot "${rootfs_path}" /bin/bash -s << EOF
mkdir /run/lock
locale-gen
# set default boot target
ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
# override getty@.service for container ttys
sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \
-e 's/After=dev-%i.device/After=/' \
< /lib/systemd/system/getty\@.service \
> /etc/systemd/system/getty\@.service
# fix systemd-sysctl service
sed -e 's/^ConditionPathIsReadWrite=\/proc\/sys\/$/ConditionPathIsReadWrite=\/proc\/sys\/net\//' \
-e 's/^ExecStart=\/usr\/lib\/systemd\/systemd-sysctl$/ExecStart=\/usr\/lib\/systemd\/systemd-sysctl --prefix net/' \
-i /usr/lib/systemd/system/systemd-sysctl.service
# initialize pacman keyring
pacman-key --init
pacman-key --populate archlinux
# enable networkd
systemctl enable systemd-networkd
systemctl enable systemd-resolved
ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
EOF
# enable getty on active ttys
local nttys=$(cat "${config_path}/config" ${shared_config} ${common_config} | grep "^lxc.tty.max" | head -n1 | cut -d= -f2 | tr -d "[:blank:]")
local devttydir=$(cat "${config_path}/config" ${shared_config} ${common_config} | grep "^lxc.tty.dir" | head -n1 | cut -d= -f2 | tr -d "[:blank:]")
local devtty=""
# bind getty instances to /dev/<devttydir>/tty* if lxc.tty.dir is set
[ -n "${devttydir}" ] && devtty="${devttydir}-"
if [ ${nttys:-0} -gt 1 ]; then
( cd "${rootfs_path}/etc/systemd/system/getty.target.wants"
for i in $(seq 1 $nttys); do ln -sf "../getty@.service" "getty@${devtty}tty${i}.service"; done )
fi
# update securetty to allow console login if devttydir is set
if [ -n "${devttydir}" ]; then
for i in $(seq 1 ${nttys:-1}); do
echo "${devttydir}/tty${i}" >> "${rootfs_path}/etc/securetty"
done
fi
[ -n "${devttydir}" ] && echo "${devttydir}/console" >> "${rootfs_path}/etc/securetty"
# Arch default configuration allows only tty1-6 for login
[ ${nttys:-0} -gt 6 ] && echo \
"You may want to modify container's /etc/securetty \
file to allow root logins on tty7 and higher"
return 0
}
# write container configuration files
copy_configuration() {
mkdir -p "${config_path}"
local config="${config_path}/config"
echo "lxc.uts.name = ${name}" >> "${config}"
grep -q "^lxc.arch" "${config}" 2>/dev/null \
|| echo "lxc.arch = ${arch}" >> "${config}"
grep -q "^lxc.rootfs.path" "${config}" 2>/dev/null \
|| echo "lxc.rootfs.path = ${rootfs_path}" >> "${config}"
[ -e "${shared_config}" ] \
&& echo "lxc.include = ${shared_config}" >> "${config}"
if [ $? -ne 0 ]; then
echo "Failed to configure container"
return 1
fi
return 0
}
# install packages within container chroot
install_arch() {
[ "${arch}" != "$(uname -m)" ] && different_arch=true
if [ "${different_arch}" = "true" ]; then
container_pacman_config=$(mktemp)
container_mirrorlist=$(mktemp)
sed -e "s:Architecture =.*:Architecture = ${arch}:g" \
-e "s:/etc/pacman.d/mirrorlist:${container_mirrorlist}:g" \
"${pacman_config}" > "${container_pacman_config}"
sed -e "s:\(x86_64\|\$arch\):${arch}:g" \
/etc/pacman.d/mirrorlist > "${container_mirrorlist}"
pacman_config="${container_pacman_config}"
fi
if ! pacstrap -dcGC "${pacman_config}" "${rootfs_path}" \
${base_packages[@]}; then
echo "Failed to install container packages"
return 1
fi
if [ "${different_arch}" = "true" ]; then
sed -i -e "s:Architecture =.*:Architecture = ${arch}:g" \
"${rootfs_path}"/etc/pacman.conf
cp "${container_mirrorlist}" "${rootfs_path}"/etc/pacman.d/mirrorlist
rm "${container_pacman_config}" "${container_mirrorlist}"
fi
[ -d "${rootfs_path}/lib/modules" ] && ldconfig -r "${rootfs_path}"
return 0
}
usage() {
cat <<EOF
usage:
${1} -n|--name=<container_name> [-p|--path=<path>] [-a|--arch=<arch of the container>]
[-r|--root_password=<root password>] [-P|--packages=<pkg1,pkg2,...>]
[-e|--enable_units=unit1,unit2...] [-d|--disable_units=unit1,unit2...]
[-c|--config=<pacman config path>] [-h|--help]
Mandatory args:
-n,--name container name, used to as an identifier for that container from now on
Optional args:
-p,--path path to where the container rootfs will be created (${default_path})
--rootfs path for actual container rootfs, (${default_path}/rootfs)
-P,--packages preinstall additional packages, comma-separated list
-e,--enable_units enable systemd services, comma-separated list
-d,--disable_units disable systemd services, comma-separated list
-c,--config use specified pacman config when installing container packages
-a,--arch use specified architecture instead of host's architecture
-r,--root_password set container root password
-h,--help print this help
EOF
return 0
}
options=$(getopt -o hp:P:e:d:n:c:a:r: -l help,rootfs:,path:,packages:,enable_units:,disable_units:,name:,config:,arch:,root_password: -- "${@}")
if [ ${?} -ne 0 ]; then
usage $(basename ${0})
exit 1
fi
eval set -- "${options}"
while true
do
case "${1}" in
-h|--help) usage ${0} && exit 0;;
-p|--path) path=${2}; shift 2;;
-n|--name) name=${2}; shift 2;;
--rootfs) rootfs_path=${2}; shift 2;;
-P|--packages) additional_packages=${2}; shift 2;;
-e|--enable_units) enable_units=${2}; shift 2;;
-d|--disable_units) disable_units=${2}; shift 2;;
-c|--config) pacman_config=${2}; shift 2;;
-a|--arch) arch=${2}; shift 2;;
-r|--root_password) root_passwd=${2}; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
if [ -z "${name}" ]; then
echo "missing required 'name' parameter"
exit 1
fi
type pacman >/dev/null 2>&1
if [ ${?} -ne 0 ]; then
echo "'pacman' command is missing, refer to wiki.archlinux.org for information about installing pacman"
exit 1
fi
if [ -z "${path}" ]; then
path="${default_path}/${name}"
fi
if [ "${EUID}" != "0" ]; then
echo "This script should be run as 'root'"
exit 1
fi
if [ -z "$rootfs_path" ]; then
rootfs_path="${path}/rootfs"
fi
config_path="${path}"
revert() {
echo "Interrupted, cleaning up"
lxc-destroy -n "${name}"
rm -rf "${path}/${name}"
rm -rf "${default_path}/${name}"
exit 1
}
trap revert SIGHUP SIGINT SIGTERM
copy_configuration
if [ ${?} -ne 0 ]; then
echo "failed to write configuration file"
rm -rf "${config_path}"
exit 1
fi
if [ ${#additional_packages[@]} -gt 0 ]; then
split_string ${additional_packages}
base_packages+=(${result[@]})
fi
mkdir -p "${rootfs_path}"
install_arch
if [ ${?} -ne 0 ]; then
echo "failed to install Arch Linux"
rm -rf "${config_path}" "${path}"
exit 1
fi
configure_arch
if [ ${?} -ne 0 ]; then
echo "failed to configure Arch Linux for a container"
rm -rf "${config_path}" "${path}"
exit 1
fi
if [ ${#enable_units[@]} -gt 0 ]; then
split_string ${enable_units}
for unit in ${result[@]}; do
[ "${unit##*.}" = "service" ] || unit="${unit}.service"
ln -s "/usr/lib/systemd/system/${unit}" \
"${rootfs_path}/etc/systemd/system/multi-user.target.wants/"
done
fi
if [ ${#disable_units[@]} -gt 0 ]; then
split_string ${disable_units}
for unit in ${result[@]}; do
[ "${unit##*.}" = "service" ] || unit="${unit}.service"
ln -s /dev/null "${rootfs_path}/etc/systemd/system/${unit}"
done
fi
if [ -n "${root_passwd}" ]; then
echo "root:${root_passwd}" | chroot "${rootfs_path}" chpasswd
fi
cat << EOF
Arch Linux container ${name} is successfully created! The configuration is
stored in ${config_path}/config. Please refer to https://wiki.archlinux.org for
information about configuring Arch Linux.
EOF

484
templates/lxc-busybox.in Normal file
View File

@ -0,0 +1,484 @@
#!/bin/bash
#
# lxc: linux Container library
# Authors:
# Daniel Lezcano <daniel.lezcano@free.fr>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
LXC_MAPPED_UID=
LXC_MAPPED_GID=
SSH=
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
am_in_userns() {
[ -e /proc/self/uid_map ] || { echo no; return; }
[ "$(wc -l /proc/self/uid_map | awk '{ print $1 }')" -eq 1 ] || { echo yes; return; }
line=$(awk '{ print $1 " " $2 " " $3 }' /proc/self/uid_map)
[ "$line" = "0 0 4294967295" ] && { echo no; return; }
echo yes
}
in_userns=0
[ $(am_in_userns) = "yes" ] && in_userns=1
copy_binary()
{
binary_path=`which $1`
if [ $? -ne 0 ]; then
echo "Unable to find $1 binary on the system"
return 1
fi
dir_path="${binary_path%/*}"
echo /{,usr/}{,s}bin | grep $dir_path >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Binary $1 is located at $binary_path and will not be copied"
echo "($dir_path not supported)"
return 1
fi
cp $binary_path $rootfs/$binary_path
if [ $? -ne 0 ]; then
echo "Failed to copy $binary_path to rootfs"
return 1
fi
return 0
}
install_busybox()
{
rootfs=$1
name=$2
res=0
tree="\
$rootfs/selinux \
$rootfs/dev \
$rootfs/home \
$rootfs/root \
$rootfs/etc \
$rootfs/etc/init.d \
$rootfs/bin \
$rootfs/usr/bin \
$rootfs/sbin \
$rootfs/usr/sbin \
$rootfs/proc \
$rootfs/sys \
$rootfs/mnt \
$rootfs/tmp \
$rootfs/var/log \
$rootfs/usr/share/udhcpc \
$rootfs/dev/pts \
$rootfs/dev/shm \
$rootfs/lib \
$rootfs/usr/lib \
$rootfs/lib64 \
$rootfs/usr/lib64"
mkdir -p $tree || return 1
chmod 755 $tree || return 1
pushd $rootfs/dev > /dev/null || return 1
# minimal devices needed for busybox
if [ $in_userns -eq 1 ]; then
for dev in tty console tty0 tty1 ram0 null urandom; do
echo "lxc.mount.entry = /dev/$dev dev/$dev none bind,optional,create=file 0 0" >> $path/config
done
else
mknod -m 666 tty c 5 0 || res=1
mknod -m 666 console c 5 1 || res=1
mknod -m 666 tty0 c 4 0 || res=1
mknod -m 666 tty1 c 4 0 || res=1
mknod -m 666 tty5 c 4 0 || res=1
mknod -m 600 ram0 b 1 0 || res=1
mknod -m 666 null c 1 3 || res=1
mknod -m 666 zero c 1 5 || res=1
mknod -m 666 urandom c 1 9 || res=1
fi
popd > /dev/null
# root user defined
cat <<EOF >> $rootfs/etc/passwd
root:x:0:0:root:/root:/bin/sh
EOF
cat <<EOF >> $rootfs/etc/group
root:x:0:root
EOF
# mount everything
cat <<EOF >> $rootfs/etc/init.d/rcS
#!/bin/sh
/bin/syslogd
/bin/mount -a
/bin/udhcpc
EOF
# executable
chmod 744 $rootfs/etc/init.d/rcS || return 1
# launch rcS first then make a console available
# and propose a shell on the tty, the last one is
# not needed
cat <<EOF >> $rootfs/etc/inittab
::sysinit:/etc/init.d/rcS
tty1::respawn:/bin/getty -L tty1 115200 vt100
console::askfirst:/bin/sh
EOF
# writable and readable for other
chmod 644 $rootfs/etc/inittab || return 1
cat <<EOF >> $rootfs/usr/share/udhcpc/default.script
#!/bin/sh
case "\$1" in
deconfig)
ip addr flush dev \$interface
;;
renew|bound)
# flush all the routes
if [ -n "\$router" ]; then
ip route del default 2> /dev/null
fi
# check broadcast
if [ -n "\$broadcast" ]; then
broadcast="broadcast \$broadcast"
fi
# add a new ip address
ip addr add \$ip/\$mask \$broadcast dev \$interface
if [ -n "\$router" ]; then
ip route add default via \$router dev \$interface
fi
[ -n "\$domain" ] && echo search \$domain > /etc/resolv.conf
for i in \$dns ; do
echo nameserver \$i >> /etc/resolv.conf
done
;;
esac
exit 0
EOF
chmod 744 $rootfs/usr/share/udhcpc/default.script
return $res
}
install_dropbear()
{
# copy dropbear binary
copy_binary dropbear || return 1
# make symlinks to various ssh utilities
utils="\
$rootfs/usr/bin/dbclient \
$rootfs/usr/bin/scp \
$rootfs/usr/bin/ssh \
$rootfs/usr/sbin/dropbearkey \
$rootfs/usr/sbin/dropbearconvert \
"
echo $utils | xargs -n1 ln -s /usr/sbin/dropbear
# add necessary config files
mkdir $rootfs/etc/dropbear
dropbearkey -t rsa -f $rootfs/etc/dropbear/dropbear_rsa_host_key > /dev/null 2>&1
dropbearkey -t dss -f $rootfs/etc/dropbear/dropbear_dss_host_key > /dev/null 2>&1
echo "'dropbear' ssh utility installed"
return 0
}
install_openssh()
{
# tools to be installed
server_utils="sshd"
client_utils="\
ssh \
scp \
"
client_optional_utils="\
sftp \
ssh-add \
ssh-agent \
ssh-keygen \
ssh-keyscan \
ssh-argv0 \
ssh-copy-id \
"
# new folders used by ssh
ssh_tree="\
$rootfs/etc/ssh \
$rootfs/var/empty/sshd \
$rootfs/var/lib/empty/sshd \
$rootfs/var/run/sshd \
"
# create folder structure
mkdir -p $ssh_tree
if [ $? -ne 0 ]; then
return 1
fi
# copy binaries
for bin in $server_utils $client_utils; do
copy_binary $bin || return 1
done
for bin in $client_optional_utils; do
tool_path=`which $bin` && copy_binary $bin
done
# add user and group
cat <<EOF >> $rootfs/etc/passwd
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
EOF
cat <<EOF >> $rootfs/etc/group
sshd:x:74:
EOF
# generate container keys
ssh-keygen -t rsa -N "" -f $rootfs/etc/ssh/ssh_host_rsa_key >/dev/null 2>&1
ssh-keygen -t dsa -N "" -f $rootfs/etc/ssh/ssh_host_dsa_key >/dev/null 2>&1
# by default setup root password with no password
cat <<EOF > $rootfs/etc/ssh/sshd_config
Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
UsePrivilegeSeparation yes
KeyRegenerationInterval 3600
ServerKeyBits 768
SyslogFacility AUTH
LogLevel INFO
LoginGraceTime 120
PermitRootLogin yes
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
IgnoreRhosts yes
RhostsRSAAuthentication no
HostbasedAuthentication no
PermitEmptyPasswords yes
ChallengeResponseAuthentication no
EOF
echo "'OpenSSH' utility installed"
return 0
}
configure_busybox()
{
rootfs=$1
which busybox >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "busybox executable is not accessible"
return 1
fi
# copy busybox in the rootfs
cp $(which busybox) $rootfs/bin
if [ $? -ne 0 ]; then
echo "failed to copy busybox in the rootfs"
return 1
fi
# symlink busybox for the commands it supports
# it would be nice to just use "chroot $rootfs busybox --install -s /bin"
# but that only works right in a chroot with busybox >= 1.19.0
pushd $rootfs/bin > /dev/null || return 1
./busybox --help | grep 'Currently defined functions:' -A300 | \
grep -v 'Currently defined functions:' | tr , '\n' | \
xargs -n1 ln -s busybox
popd > /dev/null
# relink /sbin/init
ln $rootfs/bin/busybox $rootfs/sbin/init
# /etc/fstab must exist for "mount -a"
touch $rootfs/etc/fstab
# passwd exec must be setuid
chmod +s $rootfs/bin/passwd
touch $rootfs/etc/shadow
return 0
}
copy_configuration()
{
path=$1
rootfs=$2
name=$3
grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs" >> $path/config
cat <<EOF >> $path/config
lxc.signal.halt = SIGUSR1
lxc.signal.reboot = SIGTERM
lxc.uts.name = $name
lxc.tty.max = 1
lxc.pty.max = 1
lxc.cap.drop = sys_module mac_admin mac_override sys_time
# When using LXC with apparmor, uncomment the next line to run unconfined:
#lxc.apparmor.profile = unconfined
lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
lxc.mount.entry = shm /dev/shm tmpfs defaults 0 0
EOF
libdirs="\
lib \
usr/lib \
lib64 \
usr/lib64"
for dir in $libdirs; do
if [ -d "/$dir" ] && [ -d "$rootfs/$dir" ]; then
echo "lxc.mount.entry = /$dir $dir none ro,bind 0 0" >> $path/config
fi
done
echo "lxc.mount.entry = /sys/kernel/security sys/kernel/security none ro,bind,optional 0 0" >>$path/config
}
remap_userns()
{
path=$1
if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then
chown $LXC_MAPPED_UID $path/config >/dev/null 2>&1
chown -R root $path/rootfs >/dev/null 2>&1
fi
if [ -n "$LXC_MAPPED_GID" ] && [ "$LXC_MAPPED_GID" != "-1" ]; then
chgrp $LXC_MAPPED_GID $path/config >/dev/null 2>&1
chgrp -R root $path/rootfs >/dev/null 2>&1
fi
}
usage()
{
cat <<EOF
$1 -h|--help -p|--path=<path> -s|--ssh={dropbear,openssh}
EOF
return 0
}
options=$(getopt -o hp:n:s: -l help,rootfs:,path:,name:,mapped-uid:,mapped-gid:,ssh: -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
fi
eval set -- "$options"
while true
do
case "$1" in
-h|--help) usage $0 && exit 0;;
-p|--path) path=$2; shift 2;;
--rootfs) rootfs=$2; shift 2;;
-n|--name) name=$2; shift 2;;
--mapped-uid) LXC_MAPPED_UID=$2; shift 2;;
--mapped-gid) LXC_MAPPED_GID=$2; shift 2;;
-s|--ssh) SSH=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
if [ "$(id -u)" != "0" ]; then
echo "This script should be run as 'root'"
exit 1
fi
if [ -z "$path" ]; then
echo "'path' parameter is required"
exit 1
fi
# detect rootfs
config="$path/config"
if [ -z "$rootfs" ]; then
if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then
rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config)
else
rootfs=$path/rootfs
fi
fi
install_busybox $rootfs $name
if [ $? -ne 0 ]; then
echo "failed to install busybox's rootfs"
exit 1
fi
configure_busybox $rootfs
if [ $? -ne 0 ]; then
echo "failed to configure busybox template"
exit 1
fi
copy_configuration $path $rootfs $name
if [ $? -ne 0 ]; then
echo "failed to write configuration file"
exit 1
fi
remap_userns $path
if [ $? -ne 0 ]; then
echo "failed to remap files to user"
exit 1
fi
if [ -n "$SSH" ]; then
case "$SSH" in
"dropbear")
install_dropbear
if [ $? -ne 0 ]; then
echo "Unable to install 'dropbear' ssh utility"
exit 1
fi ;;
"openssh")
install_openssh
if [ $? -ne 0 ]; then
echo "Unable to install 'OpenSSH' utility"
exit 1
fi ;;
*)
echo "$SSH: unrecognized ssh utility"
exit 1
esac
else
which dropbear >/dev/null 2>&1
if [ $? -eq 0 ]; then
install_dropbear
fi
fi

968
templates/lxc-centos.in Normal file
View File

@ -0,0 +1,968 @@
#!/bin/bash
#
# template script for generating CentOS container for LXC
#
# lxc: linux Container library
# Authors:
# Daniel Lezcano <daniel.lezcano@free.fr>
# Ramez Hanna <rhanna@informatiq.org>
# Fajar A. Nugraha <github@fajar.net>
# Michael H. Warfield <mhw@WittsEnd.com>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#Configurations
default_path=@LXCPATH@
# Some combinations of the tuning knobs below do not exactly make sense.
# but that's ok.
#
# If the "root_password" is non-blank, use it, else set a default.
# This can be passed to the script as an environment variable and is
# set by a shell conditional assignment. Looks weird but it is what it is.
#
# If the root password contains a ding ($) then try to expand it.
# That will pick up things like ${name} and ${RANDOM}.
# If the root password contains more than 3 consecutive X's, pass it as
# a template to mktemp and take the result.
#
# If root_display_password = yes, display the temporary root password at exit.
# If root_store_password = yes, store it in the configuration directory
# If root_prompt_password = yes, invoke "passwd" to force the user to change
# the root password after the container is created.
# If root_expire_password = yes, you will be prompted to change the root
# password at the first login.
#
# These are conditional assignments... The can be overridden from the
# preexisting environment variables...
#
# Make sure this is in single quotes to defer expansion to later!
# :{root_password='Root-${name}-${RANDOM}'}
: ${root_password='Root-${name}-XXXXXX'}
# Now, it doesn't make much sense to display, store, and force change
# together. But, we gotta test, right???
: ${root_display_password='no'}
: ${root_store_password='yes'}
# Prompting for something interactive has potential for mayhem
# with users running under the API... Don't default to "yes"
: ${root_prompt_password='no'}
# Expire root password? Default to yes, but can be overridden from
# the environment variable
: ${root_expire_password='yes'}
# These are only going into comments in the resulting config...
lxc_network_type=veth
lxc_network_link=lxcbr0
# is this CentOS?
# Alow for weird remixes like the Raspberry Pi
#
# Use the Mitre standard CPE identifier for the release ID if possible...
# This may be in /etc/os-release or /etc/system-release-cpe. We
# should be able to use EITHER. Give preference to /etc/os-release for now.
# Detect use under userns (unsupported)
for arg in "$@"; do
[ "$arg" = "--" ] && break
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
echo "This template can't be used for unprivileged containers." 1>&2
echo "You may want to try the \"download\" template instead." 1>&2
exit 1
fi
done
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
if [ -e /etc/os-release ]
then
# This is a shell friendly configuration file. We can just source it.
# What we're looking for in here is the ID, VERSION_ID and the CPE_NAME
. /etc/os-release
echo "Host CPE ID from /etc/os-release: ${CPE_NAME}"
fi
if [ "${CPE_NAME}" = "" -a -e /etc/system-release-cpe ]
then
CPE_NAME=$(head -n1 /etc/system-release-cpe)
CPE_URI=$(expr ${CPE_NAME} : '\([^:]*:[^:]*\)')
if [ "${CPE_URI}" != "cpe:/o" ]
then
CPE_NAME=
else
# Probably a better way to do this but sill remain posix
# compatible but this works, shrug...
# Must be nice and not introduce convenient bashisms here.
#
# According to the official registration at Mitre and NIST,
# this should have been something like this for CentOS:
# cpe:/o:centos:centos:6
# or this:
# cpe:/o:centos:centos:6.5
#
ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:\([^:]*\)')
# The "enterprise_linux" is a bone toss back to RHEL.
# Since CentOS and RHEL are so tightly coupled, we'll
# take the RHEL version if we're running on it and do the
# equivalent version for CentOS.
if [ ${ID} = "linux" -o ${ID} = "enterprise_linux" ]
then
# Instead we got this: cpe:/o:centos:linux:6
ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:\([^:]*\)')
fi
VERSION_ID=$(expr ${CPE_NAME} : '[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\)')
echo "Host CPE ID from /etc/system-release-cpe: ${CPE_NAME}"
fi
fi
if [ "${CPE_NAME}" != "" -a "${ID}" = "centos" -a "${VERSION_ID}" != "" ]
then
centos_host_ver=${VERSION_ID}
is_centos=true
elif [ "${CPE_NAME}" != "" -a "${ID}" = "redhat" -o "${ID}" = "rhel" -a "${VERSION_ID}" != "" ]
then
# RHEL 7+ /etc/os-release ID = 'rhel', which doesn't enter this elif without the added OR statement
redhat_host_ver=${VERSION_ID}
is_redhat=true
elif [ -e /etc/centos-release ]
then
# Only if all other methods fail, try to parse the redhat-release file.
centos_host_ver=$( sed -e '/^CentOS /!d' -e 's/CentOS.*\srelease\s*\([0-9][0-9.]*\)\s.*/\1/' < /etc/centos-release )
if [ "$centos_host_ver" != "" ]
then
is_centos=true
fi
fi
force_mknod()
{
# delete a device node if exists, and create a new one
rm -f $2 && mknod -m $1 $2 $3 $4 $5
}
configure_centos()
{
# disable selinux in CentOS
mkdir -p $rootfs_path/selinux
echo 0 > $rootfs_path/selinux/enforce
# Also kill it in the /etc/selinux/config file if it's there...
if [ -f $rootfs_path/etc/selinux/config ]
then
sed -i '/^SELINUX=/s/.*/SELINUX=disabled/' $rootfs_path/etc/selinux/config
fi
# Nice catch from Dwight Engen in the Oracle template.
# Wantonly plagerized here with much appreciation.
if [ -f $rootfs_path/usr/sbin/selinuxenabled ]; then
mv $rootfs_path/usr/sbin/selinuxenabled $rootfs_path/usr/sbin/selinuxenabled.lxcorig
ln -s /bin/false $rootfs_path/usr/sbin/selinuxenabled
fi
# This is a known problem and documented in RedHat bugzilla as relating
# to a problem with auditing enabled. This prevents an error in
# the container "Cannot make/remove an entry for the specified session"
sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/login
sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/sshd
if [ -f ${rootfs_path}/etc/pam.d/crond ]
then
sed -i '/^session.*pam_loginuid.so/s/^session/# session/' ${rootfs_path}/etc/pam.d/crond
fi
# In addition to disabling pam_loginuid in the above config files
# we'll also disable it by linking it to pam_permit to catch any
# we missed or any that get installed after the container is built.
#
# Catch either or both 32 and 64 bit archs.
if [ -f ${rootfs_path}/lib/security/pam_loginuid.so ]
then
( cd ${rootfs_path}/lib/security/
mv pam_loginuid.so pam_loginuid.so.disabled
ln -s pam_permit.so pam_loginuid.so
)
fi
if [ -f ${rootfs_path}/lib64/security/pam_loginuid.so ]
then
( cd ${rootfs_path}/lib64/security/
mv pam_loginuid.so pam_loginuid.so.disabled
ln -s pam_permit.so pam_loginuid.so
)
fi
# Set default localtime to the host localtime if not set...
if [ -e /etc/localtime -a ! -e ${rootfs_path}/etc/localtime ]
then
# if /etc/localtime is a symlink, this should preserve it.
cp -a /etc/localtime ${rootfs_path}/etc/localtime
fi
# Deal with some dain bramage in the /etc/init.d/halt script.
# Trim it and make it our own and link it in before the default
# halt script so we can intercept it. This also preventions package
# updates from interferring with our interferring with it.
#
# There's generally not much in the halt script that useful but what's
# in there from resetting the hardware clock down is generally very bad.
# So we just eliminate the whole bottom half of that script in making
# ourselves a copy. That way a major update to the init scripts won't
# trash what we've set up.
if [ -f ${rootfs_path}/etc/init.d/halt ]
then
sed -e '/hwclock/,$d' \
< ${rootfs_path}/etc/init.d/halt \
> ${rootfs_path}/etc/init.d/lxc-halt
echo '$command -f' >> ${rootfs_path}/etc/init.d/lxc-halt
chmod 755 ${rootfs_path}/etc/init.d/lxc-halt
# Link them into the rc directories...
(
cd ${rootfs_path}/etc/rc.d/rc0.d
ln -s ../init.d/lxc-halt S00lxc-halt
cd ${rootfs_path}/etc/rc.d/rc6.d
ln -s ../init.d/lxc-halt S00lxc-reboot
)
fi
# configure the network using the dhcp
cat <<EOF > ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
HOSTNAME=${utsname}
NM_CONTROLLED=no
TYPE=Ethernet
MTU=${MTU}
DHCP_HOSTNAME=\`hostname\`
EOF
# set the hostname
cat <<EOF > ${rootfs_path}/etc/sysconfig/network
NETWORKING=yes
HOSTNAME=${utsname}
EOF
# set minimal hosts
cat <<EOF > $rootfs_path/etc/hosts
127.0.0.1 localhost $name
EOF
# set minimal fstab
cat <<EOF > $rootfs_path/etc/fstab
/dev/root / rootfs defaults 0 0
EOF
# create lxc compatibility init script
if [ "$release" = "6" ]; then
cat <<EOF > $rootfs_path/etc/init/lxc-sysinit.conf
start on startup
env container
pre-start script
if [ "x\$container" != "xlxc" -a "x\$container" != "xlibvirt" ]; then
stop;
fi
rm -f /var/lock/subsys/*
rm -f /var/run/*.pid
[ -e /etc/mtab ] || ln -s /proc/mounts /etc/mtab
mkdir -p /dev/shm
mount -t tmpfs -o nosuid,nodev tmpfs /dev/shm
initctl start tty TTY=console
telinit 3
exit 0
end script
EOF
elif [ "$release" = "5" ]; then
cat <<EOF > $rootfs_path/etc/rc.d/lxc.sysinit
#! /bin/bash
rm -f /etc/mtab /var/run/*.{pid,lock} /var/lock/subsys/*
rm -rf {/,/var}/tmp/*
echo "/dev/root / rootfs defaults 0 0" > /etc/mtab
exit 0
EOF
chmod 755 $rootfs_path/etc/rc.d/lxc.sysinit
sed -i 's|si::sysinit:/etc/rc.d/rc.sysinit|si::bootwait:/etc/rc.d/lxc.sysinit|' $rootfs_path/etc/inittab
# prevent mingetty from calling vhangup(2) since it fails with userns.
# Same issue as oracle template: prevent mingetty from calling vhangup(2)
# commit 2e83f7201c5d402478b9849f0a85c62d5b9f1589.
sed -i 's|^1:|co:2345:respawn:/sbin/mingetty --nohangup console\n1:|' $rootfs_path/etc/inittab
sed -i 's|^\([56]:\)|#\1|' $rootfs_path/etc/inittab
fi
dev_path="${rootfs_path}/dev"
rm -rf $dev_path
mkdir -p $dev_path
mknod -m 666 ${dev_path}/null c 1 3
mknod -m 666 ${dev_path}/zero c 1 5
mknod -m 666 ${dev_path}/random c 1 8
mknod -m 666 ${dev_path}/urandom c 1 9
mkdir -m 755 ${dev_path}/pts
mkdir -m 1777 ${dev_path}/shm
mknod -m 666 ${dev_path}/tty c 5 0
mknod -m 666 ${dev_path}/tty0 c 4 0
mknod -m 666 ${dev_path}/tty1 c 4 1
mknod -m 666 ${dev_path}/tty2 c 4 2
mknod -m 666 ${dev_path}/tty3 c 4 3
mknod -m 666 ${dev_path}/tty4 c 4 4
mknod -m 600 ${dev_path}/console c 5 1
mknod -m 666 ${dev_path}/full c 1 7
mknod -m 600 ${dev_path}/initctl p
mknod -m 666 ${dev_path}/ptmx c 5 2
# setup console and tty[1-4] for login. note that /dev/console and
# /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and
# /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks.
# lxc will maintain these links and bind mount ptys over /dev/lxc/*
# since lxc.tty.dir is specified in the config.
# allow root login on console, tty[1-4], and pts/0 for libvirt
echo "# LXC (Linux Containers)" >>${rootfs_path}/etc/securetty
echo "lxc/console" >>${rootfs_path}/etc/securetty
echo "lxc/tty1" >>${rootfs_path}/etc/securetty
echo "lxc/tty2" >>${rootfs_path}/etc/securetty
echo "lxc/tty3" >>${rootfs_path}/etc/securetty
echo "lxc/tty4" >>${rootfs_path}/etc/securetty
echo "# For libvirt/Virtual Machine Monitor" >>${rootfs_path}/etc/securetty
echo "pts/0" >>${rootfs_path}/etc/securetty
# prevent mingetty from calling vhangup(2) since it fails with userns.
# Same issue as oracle template: prevent mingetty from calling vhangup(2)
# commit 2e83f7201c5d402478b9849f0a85c62d5b9f1589.
test -f $rootfs_path/etc/init/tty.conf && sed -i 's|mingetty|mingetty --nohangup|' $rootfs_path/etc/init/tty.conf
if [ ${root_display_password} = "yes" ]
then
echo "Setting root password to '$root_password'"
fi
if [ ${root_store_password} = "yes" ]
then
touch ${config_path}/tmp_root_pass
chmod 600 ${config_path}/tmp_root_pass
echo ${root_password} > ${config_path}/tmp_root_pass
echo "Storing root password in '${config_path}/tmp_root_pass'"
fi
echo "root:$root_password" | chroot $rootfs_path chpasswd
if [ ${root_expire_password} = "yes" ]
then
# Also set this password as expired to force the user to change it!
chroot $rootfs_path passwd -e root
fi
# This will need to be enhanced for CentOS 7 when systemd
# comes into play... /\/\|=mhw=|\/\/
return 0
}
configure_centos_init()
{
test -f ${rootfs_path}/etc/rc.sysinit && sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.sysinit
test -f ${rootfs_path}/etc/rc.d/rc.sysinit && sed -i 's|.sbin.start_udev||' ${rootfs_path}/etc/rc.d/rc.sysinit
if [ "$release" = "6" ]; then
chroot ${rootfs_path} chkconfig udev-post off
fi
chroot ${rootfs_path} chkconfig network on
if [ "$release" = "7" ]; then
# don't wait for the timeout
chroot ${rootfs_path} chkconfig systemd-remount-fs off
fi
if [ -d ${rootfs_path}/etc/init ]
then
# This is to make upstart honor SIGPWR
cat <<EOF >${rootfs_path}/etc/init/power-status-changed.conf
# power-status-changed - shutdown on SIGPWR
#
start on power-status-changed
exec /sbin/shutdown -h now "SIGPWR received"
EOF
fi
}
download_centos()
{
# check the mini CentOS was not already downloaded
INSTALL_ROOT=$cache/partial
mkdir -p $INSTALL_ROOT
if [ $? -ne 0 ]; then
echo "Failed to create '$INSTALL_ROOT' directory"
return 1
fi
# download a mini CentOS into a cache
echo "Downloading CentOS minimal ..."
YUM0="yum --installroot $INSTALL_ROOT -y --nogpgcheck"
if yum -h | grep -q 'releasever=RELEASEVER'; then
YUM="$YUM0 --releasever=$release"
else
YUM="$YUM0"
fi
PKG_LIST="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils cronie"
# use temporary repository definition
# always prefer the repo given by the user
# if no repo given, use mirrorlist.centos.org for i386 and x86_64
# and http://mirror.centos.org/altarch/ otherwise
REPO_FILE=$INSTALL_ROOT/etc/yum.repos.d/lxc-centos-temp.repo
mkdir -p $(dirname $REPO_FILE)
if [ -n "$repo" ]; then
cat <<EOF > $REPO_FILE
[base]
name=local repository
baseurl="$repo"
EOF
elif [ ${basearch} = 'i386' ] || [ ${basearch} = 'x86_64' ]; then
cat <<EOF > $REPO_FILE
[base]
name=CentOS-$release - Base
mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=os
[updates]
name=CentOS-$release - Updates
mirrorlist=http://mirrorlist.centos.org/?release=$release&arch=$basearch&repo=updates
EOF
else
cat <<EOF > $REPO_FILE
[base]
name=CentOS-$release - Base
baseurl=http://mirror.centos.org/altarch/7/os/$basearch/
[updates]
name=CentOS-$release - Updates
baseurl=http://mirror.centos.org/altarch/7/updates/$basearch/
EOF
fi
# create minimal device nodes, needed for "yum install" and "yum update" process
mkdir -p $INSTALL_ROOT/dev
force_mknod 666 $INSTALL_ROOT/dev/null c 1 3
force_mknod 666 $INSTALL_ROOT/dev/urandom c 1 9
# create /run directory, just in case it is missing (e.g. RHEL7)
mkdir -p $INSTALL_ROOT/run
$YUM install $PKG_LIST
# create symlink for /var/run -> ../run
if [ "$release" = "7" ]; then
mv $INSTALL_ROOT/var/run/* $INSTALL_ROOT/run/
rmdir $INSTALL_ROOT/var/run
ln -sf ../run $INSTALL_ROOT/var/run
fi
if [ $? -ne 0 ]; then
echo "Failed to download the rootfs, aborting."
return 1
fi
# use same nameservers as hosts, needed for "yum update later"
cp /etc/resolv.conf $INSTALL_ROOT/etc/
# check whether rpmdb is under $HOME
if [ ! -e $INSTALL_ROOT/var/lib/rpm/Packages -a -e $INSTALL_ROOT/$HOME/.rpmdb/Packages ]; then
echo "Fixing rpmdb location ..."
mv $INSTALL_ROOT/$HOME/.rpmdb/[A-Z]* $INSTALL_ROOT/var/lib/rpm/
rm -rf $INSTALL_ROOT/$HOME/.rpmdb
chroot $INSTALL_ROOT rpm --rebuilddb 2>/dev/null
fi
# check whether rpmdb version is correct
chroot $INSTALL_ROOT rpm --quiet -q yum 2>/dev/null
ret=$?
# if "rpm -q" doesn't work due to rpmdb version difference,
# then we need to redo the process using the newly-installed yum
if [ $ret -gt 0 ]; then
echo "Reinstalling packages ..."
mv $REPO_FILE $REPO_FILE.tmp
mkdir $INSTALL_ROOT/etc/yum.repos.disabled
mv $INSTALL_ROOT/etc/yum.repos.d/*.repo $INSTALL_ROOT/etc/yum.repos.disabled/
mv $REPO_FILE.tmp $REPO_FILE
mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/etc
cp /etc/resolv.conf $INSTALL_ROOT/$INSTALL_ROOT/etc/
mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/dev
mknod -m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev/null c 1 3
mknod -m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev/urandom c 1 9
mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/var/cache/yum
cp -al $INSTALL_ROOT/var/cache/yum/* $INSTALL_ROOT/$INSTALL_ROOT/var/cache/yum/
chroot $INSTALL_ROOT $YUM0 install $PKG_LIST
if [ $? -ne 0 ]; then
echo "Failed to download the rootfs, aborting."
return 1
fi
mv $INSTALL_ROOT/$INSTALL_ROOT $INSTALL_ROOT.tmp
rm -rf $INSTALL_ROOT
mv $INSTALL_ROOT.tmp $INSTALL_ROOT
fi
rm -f $REPO_FILE
rm -rf $INSTALL_ROOT/var/cache/yum/*
mv "$INSTALL_ROOT" "$cache/rootfs"
echo "Download complete."
return 0
}
copy_centos()
{
# make a local copy of the mini CentOS
echo -n "Copying rootfs to $rootfs_path ..."
#cp -a $cache/rootfs-$arch $rootfs_path || return 1
# i prefer rsync (no reason really)
mkdir -p $rootfs_path
rsync -SHaAX $cache/rootfs/ $rootfs_path/
echo
return 0
}
update_centos()
{
YUM="chroot $cache/rootfs yum -y --nogpgcheck"
$YUM update
if [ $? -ne 0 ]; then
return 1
fi
$YUM clean packages
}
install_centos()
{
mkdir -p /var/lock/subsys/
(
flock -x 9
if [ $? -ne 0 ]; then
echo "Cache repository is busy."
return 1
fi
echo "Checking cache download in $cache/rootfs ... "
if [ ! -e "$cache/rootfs" ]; then
download_centos
if [ $? -ne 0 ]; then
echo "Failed to download 'CentOS base'"
return 1
fi
else
echo "Cache found. Updating..."
update_centos
if [ $? -ne 0 ]; then
echo "Failed to update 'CentOS base', continuing with last known good cache"
else
echo "Update finished"
fi
fi
echo "Copy $cache/rootfs to $rootfs_path ... "
copy_centos
if [ $? -ne 0 ]; then
echo "Failed to copy rootfs"
return 1
fi
return 0
) 9>/var/lock/subsys/lxc-centos
return $?
}
create_hwaddr()
{
openssl rand -hex 5 | sed -e 's/\(..\)/:\1/g; s/^/fe/'
}
copy_configuration()
{
mkdir -p $config_path
grep -q "^lxc.rootfs.path" $config_path/config 2>/dev/null || echo "
lxc.rootfs.path = $rootfs_path
" >> $config_path/config
# The following code is to create static MAC addresses for each
# interface in the container. This code will work for multiple
# interfaces in the default config.
mv $config_path/config $config_path/config.def
while read LINE
do
# This should catch variable expansions from the default config...
if expr "${LINE}" : '.*\$' > /dev/null 2>&1
then
LINE=$(eval "echo \"${LINE}\"")
fi
# There is a tab and a space in the regex bracket below!
# Seems that \s doesn't work in brackets.
KEY=$(expr "${LINE}" : '\s*\([^ ]*\)\s*=')
if [[ "${KEY}" != "lxc.net.0.hwaddr" ]]
then
echo ${LINE} >> $config_path/config
if [[ "${KEY}" == "lxc.net.0.link" ]]
then
echo "lxc.net.0.hwaddr = $(create_hwaddr)" >> $config_path/config
fi
fi
done < $config_path/config.def
rm -f $config_path/config.def
if [ -e "@LXCTEMPLATECONFIG@/centos.common.conf" ]; then
echo "
# Include common configuration
lxc.include = @LXCTEMPLATECONFIG@/centos.common.conf
" >> $config_path/config
fi
# Append things which require expansion here...
cat <<EOF >> $config_path/config
lxc.arch = $arch
lxc.uts.name = $utsname
# When using LXC with apparmor, uncomment the next line to run unconfined:
#lxc.apparmor.profile = unconfined
# example simple networking setup, uncomment to enable
#lxc.net.0.type = $lxc_network_type
#lxc.net.0.flags = up
#lxc.net.0.link = $lxc_network_link
#lxc.net.0.name = eth0
# Additional example for veth network type
# static MAC address,
#lxc.net.0.hwaddr = 00:16:3e:77:52:20
# persistent veth device name on host side
# Note: This may potentially collide with other containers of same name!
#lxc.net.0.veth.pair = v-$name-e0
EOF
if [ $? -ne 0 ]; then
echo "Failed to add configuration"
return 1
fi
return 0
}
clean()
{
if [ ! -e $cache ]; then
exit 0
fi
# lock, so we won't purge while someone is creating a repository
(
flock -x 9
if [ $? != 0 ]; then
echo "Cache repository is busy."
exit 1
fi
echo -n "Purging the download cache for CentOS-$release..."
rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
exit 0
) 9>@LOCALSTATEDIR@/lock/subsys/lxc-centos
}
usage()
{
cat <<EOF
usage:
$1 -n|--name=<container_name>
[-p|--path=<path>] [-c|--clean] [-R|--release=<CentOS_release>] [-a|--arch=<arch of the container>]
[-h|--help]
Mandatory args:
-n,--name container name, used to as an identifier for that container from now on
Optional args:
-p,--path path to where the container rootfs will be created, defaults to /var/lib/lxc/name.
-c,--clean clean the cache
-R,--release CentOS release for the new container. If the host is CentOS, then it will default to the host's release.
--fqdn fully qualified domain name (FQDN) for DNS and system naming
--repo repository to use (url)
-a,--arch Define what arch the container will be [i686,x86_64]
-h,--help print this help
EOF
return 0
}
options=$(getopt -o a:hp:n:cR: -l help,path:,rootfs:,name:,clean,release:,repo:,arch:,fqdn: -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
fi
arch=$(uname -m)
eval set -- "$options"
while true
do
case "$1" in
-h|--help) usage $0 && exit 0;;
-p|--path) path=$2; shift 2;;
--rootfs) rootfs_path=$2; shift 2;;
-n|--name) name=$2; shift 2;;
-c|--clean) clean=1; shift 1;;
-R|--release) release=$2; shift 2;;
--repo) repo="$2"; shift 2;;
-a|--arch) newarch=$2; shift 2;;
--fqdn) utsname=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
if [ ! -z "$clean" -a -z "$path" ]; then
clean || exit 1
exit 0
fi
basearch=${arch}
# Map a few architectures to their generic CentOS repository archs.
# The two ARM archs are a bit of a guesstimate for the v5 and v6
# archs. V6 should have hardware floating point (Rasberry Pi).
# The "arm" arch is safer (no hardware floating point). So
# there may be cases where we "get it wrong" for some v6 other
# than RPi.
case "$arch" in
i686) basearch=i386 ;;
armv3l|armv4l|armv5l) basearch=arm ;;
armv6l|armv7l|armv8l) basearch=armhfp ;;
*) ;;
esac
# Somebody wants to specify an arch. This is very limited case.
# i386/i586/i686 on i386/x86_64
# - or -
# x86_64 on x86_64
if [ "${newarch}" != "" -a "${newarch}" != "${arch}" ]
then
case "${newarch}" in
i386|i586|i686)
if [ "${basearch}" = "i386" -o "${basearch}" = "x86_64" ]
then
# Make the arch a generic x86 32 bit...
arch=${newarch}
basearch=i386
else
basearch=bad
fi
;;
*)
basearch=bad
;;
esac
if [ "${basearch}" = "bad" ]
then
echo "You cannot build a ${newarch} CentOS container on a ${arch} host. Sorry!"
exit 1
fi
fi
# Allow the cache base to be set by environment variable
cache_base=${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc"}/centos/$basearch
# Let's do something better for the initial root password.
# It's not perfect but it will defeat common scanning brute force
# attacks in the case where ssh is exposed. It will also be set to
# expired, forcing the user to change it at first login.
if [ "${root_password}" = "" ]
then
root_password=Root-${name}-${RANDOM}
else
# If it's got a ding in it, try and expand it!
if [ $(expr "${root_password}" : '.*$.') != 0 ]
then
root_password=$(eval echo "${root_password}")
fi
# If it has more than 3 consecutive X's in it, feed it
# through mktemp as a template.
if [ $(expr "${root_password}" : '.*XXXX') != 0 ]
then
root_password=$(mktemp -u ${root_password})
fi
fi
if [ -z "${utsname}" ]; then
utsname=${name}
fi
# This follows a standard "resolver" convention that an FQDN must have
# at least two dots or it is considered a local relative host name.
# If it doesn't, append the dns domain name of the host system.
#
# This changes one significant behavior when running
# "lxc_create -n Container_Name" without using the
# --fqdn option.
#
# Old behavior:
# utsname and hostname = Container_Name
# New behavior:
# utsname and hostname = Container_Name.Domain_Name
if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then
if [[ "$(dnsdomainname)" != "" && "$(dnsdomainname)" != "localdomain" ]]; then
utsname=${utsname}.$(dnsdomainname)
fi
fi
type yum >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "'yum' command is missing"
exit 1
fi
if [ -z "$path" ]; then
path=$default_path/$name
fi
if [ -z "$release" ]; then
if [ "$is_centos" -a "$centos_host_ver" ]; then
release=$centos_host_ver
elif [ "$is_redhat" -a "$redhat_host_ver" ]; then
# This is needed to clean out bullshit like 6workstation and 6server.
release=$(expr $redhat_host_ver : '\([0-9.]*\)')
else
echo "This is not a CentOS or Red Hat host and release is missing, defaulting to 7, use -R|--release to specify release"
release=7
fi
fi
if [ "$(id -u)" != "0" ]; then
echo "This script should be run as 'root'"
exit 1
fi
if [ -z "$rootfs_path" ]; then
rootfs_path=$path/rootfs
# check for 'lxc.rootfs.path' passed in through default config by lxc-create
if grep -q '^lxc.rootfs.path' $path/config 2>/dev/null ; then
rootfs_path=$(sed -e '/^lxc.rootfs.path\s*=/!d' -e 's/\s*#.*//' \
-e 's/^lxc.rootfs.path\s*=\s*//' -e q $path/config)
fi
fi
config_path=$path
cache=$cache_base/$release
revert()
{
echo "Interrupted, so cleaning up"
lxc-destroy -n $name
# maybe was interrupted before copy config
rm -rf $path
echo "exiting..."
exit 1
}
trap revert SIGHUP SIGINT SIGTERM
copy_configuration
if [ $? -ne 0 ]; then
echo "failed write configuration file"
exit 1
fi
install_centos
if [ $? -ne 0 ]; then
echo "failed to install CentOS"
exit 1
fi
configure_centos
if [ $? -ne 0 ]; then
echo "failed to configure CentOS for a container"
exit 1
fi
configure_centos_init
if [ ! -z "$clean" ]; then
clean || exit 1
exit 0
fi
echo "
Container rootfs and config have been created.
Edit the config file to check/enable networking setup.
"
if [ ${root_display_password} = "yes" ]
then
echo "The temporary password for root is: '$root_password'
You may want to note that password down before starting the container.
"
fi
if [ ${root_store_password} = "yes" ]
then
echo "The temporary root password is stored in:
'${config_path}/tmp_root_pass'
"
fi
if [ ${root_prompt_password} = "yes" ]
then
echo "Invoking the passwd command in the container to set the root password.
chroot ${rootfs_path} passwd
"
chroot ${rootfs_path} passwd
else
if [ ${root_expire_password} = "yes" ]
then
if ( mountpoint -q -- "${rootfs_path}" )
then
echo "To reset the root password, you can do:
lxc-start -n ${name}
lxc-attach -n ${name} -- passwd
lxc-stop -n ${name}
"
else
echo "
The root password is set up as "expired" and will require it to be changed
at first login, which you should do as soon as possible. If you lose the
root password or wish to change it without starting the container, you
can change it from the host by running the following command (which will
also reset the expired flag):
chroot ${rootfs_path} passwd
"
fi
fi
fi

343
templates/lxc-cirros.in Normal file
View File

@ -0,0 +1,343 @@
#!/bin/bash
# template script for generating ubuntu container for LXC
#
# This script consolidates and extends the existing lxc ubuntu scripts
#
# Copyright © 2013 Canonical Ltd.
# Author: Scott Moser <scott.moser@canonical.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2, as
# published by the Free Software Foundation.
# 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.
# Detect use under userns (unsupported)
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
VERBOSITY=0
DOWNLOAD_URL="http://download.cirros-cloud.net/"
UNAME_M=$(uname -m)
ARCHES=( i386 x86_64 amd64 arm )
STREAMS=( released devel )
SOURCES=( nocloud none )
BUILD="standard"
LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
LXC_MAPPED_GID=
LXC_MAPPED_UID=
DEF_VERSION="released"
DEF_SOURCE="nocloud"
case "${UNAME_M}" in
i?86) DEF_ARCH="i386";;
x86_64) DEF_ARCH="x86_64";;
arm*) DEF_ARCH="arm";;
*) DEF_ARCH="i386";;
esac
am_in_userns() {
[ -e /proc/self/uid_map ] || { echo no; return; }
[ "$(wc -l /proc/self/uid_map | awk '{ print $1 }')" -eq 1 ] || { echo yes; return; }
line=$(awk '{ print $1 " " $2 " " $3 }' /proc/self/uid_map)
[ "$line" = "0 0 4294967295" ] && { echo no; return; }
echo yes
}
in_userns=0
[ $(am_in_userns) = "yes" ] && in_userns=1
# Allow the cache base to be set by environment variable
if [ $(id -u) -eq 0 ]; then
CACHE_D=${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc/cirros"}
else
CACHE_D=${LXC_CACHE_PATH:-"$HOME/.cache/lxc/cirros"}
fi
error() { echo "$@" 1>&2; }
inargs() {
local needle="$1" x=""
shift
for x in "$@"; do
[ "$needle" = "$x" ] && return 0
done
return 1
}
Usage() {
cat <<EOF
${0##*/} [options]
-a | --arch A architecture to use [${ARCHES[*]}]
default: ${DEF_ARCH}
-h | --help this usage
-v | --verbose increase verbosity
-S | --auth-key K insert auth key 'K'
-v | --version V version [${STREAMS[*]}]
default: ${DEF_VERSION}
-u | --userdata U user-data file
--tarball T read from tarball 'T' rather than downloading
or using cache.
--source S insert userdata/metadata via source S
[${SOURCES[*]}]
EOF
}
bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; return 1; }
debug() {
local level=${1}; shift;
[ "${level}" -gt "${VERBOSITY}" ] && return
error "${@}"
}
jsondict() {
local k="" v="" ret="{"
for arg in "$@"; do
k="${arg%%=*}"
v="${arg#*=}"
ret="${ret} \"${k}\": \"$v\","
done
ret="${ret%,} }"
echo "$ret"
}
copy_configuration()
{
local path=$1 rootfs=$2 name=$3 arch=$4 release=$5
cat >> "$path/config" <<EOF
# Template used to create this container: cirros
lxc.rootfs.path = $rootfs
lxc.tty.max = 4
lxc.pty.max = 1024
lxc.uts.name = $name
lxc.arch = $arch
lxc.cap.drop = sys_module mac_admin mac_override sys_time
# When using LXC with apparmor, uncomment the next line to run unconfined:
#lxc.apparmor.profile = unconfined
lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
lxc.cgroup.devices.deny = a
# Allow any mknod (but not using the node)
lxc.cgroup.devices.allow = c *:* m
lxc.cgroup.devices.allow = b *:* m
# /dev/null and zero
lxc.cgroup.devices.allow = c 1:3 rwm
lxc.cgroup.devices.allow = c 1:5 rwm
# consoles
lxc.cgroup.devices.allow = c 5:1 rwm
lxc.cgroup.devices.allow = c 5:0 rwm
# /dev/{,u}random
lxc.cgroup.devices.allow = c 1:9 rwm
lxc.cgroup.devices.allow = c 1:8 rwm
lxc.cgroup.devices.allow = c 136:* rwm
lxc.cgroup.devices.allow = c 5:2 rwm
# rtc
lxc.cgroup.devices.allow = c 254:0 rwm
# fuse
lxc.cgroup.devices.allow = c 10:229 rwm
# tun
lxc.cgroup.devices.allow = c 10:200 rwm
# full
lxc.cgroup.devices.allow = c 1:7 rwm
# hpet
lxc.cgroup.devices.allow = c 10:228 rwm
# kvm
lxc.cgroup.devices.allow = c 10:232 rwm
EOF
if [ $in_userns -eq 1 ] && [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.userns.conf" ]; then
echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.userns.conf" >> $path/config
fi
}
insert_ds_nocloud() {
local root_d="$1" authkey="$2" udfile="$3"
local sdir="$root_d/var/lib/cloud/seed/nocloud"
mkdir -p "$sdir" ||
{ error "failed to make datasource dir $sdir"; return 1; }
rm -f "$sdir/meta-data" "$sdir/user-data" ||
{ error "failed to clean old data from $sdir"; return 1; }
iid="iid-local01"
jsondict "instance-id=$iid" \
${authkeys:+"public-keys=${authkeys}"} > "$sdir/meta-data" ||
{ error "failed to write metadata to $sdir/meta-data"; return 1; }
if [ -n "$udfile" ]; then
cat "$udfile" > "$sdir/user-data" ||
{ error "failed to write user-data to $sdir"; return 1; }
else
rm -f "$sdir/user-data"
fi
}
insert_ds() {
local dstype="$1" root_d="$2" authkey="$3" udfile="$4"
case "$dstype" in
nocloud) insert_ds_nocloud "$root_d" "$authkey" "$udfile"
esac
}
extract_rootfs() {
local tarball="$1" rootfs_d="$2"
mkdir -p "${rootfs_d}" ||
{ error "failed to make rootfs dir ${rootfs_d}"; return 1; }
if [ $in_userns -eq 1 ]; then
tar -C "${rootfs_d}" --anchored --exclude="dev/*" -Sxzf "${tarball}" ||
{ error "failed to populate ${rootfs_d}"; return 1; }
else
tar -C "${rootfs_d}" -Sxzf "${tarball}" ||
{ error "failed to populate ${rootfs_d}"; return 1; }
fi
return 0
}
download_tarball() {
local arch="$1" ver="$2" cached="$3" baseurl="$4"
local out="" outd="" file="" dlpath=""
file="cirros-$ver-$arch-lxc.tar.gz"
dlpath="$ver/$file"
outd="${cached}/${dlpath%/*}"
if [ -f "$cached/$dlpath" ]; then
_RET="$cached/$dlpath"
return 0
fi
mkdir -p "${outd}" ||
{ error "failed to create ${outd}"; return 1; }
debug 1 "downloading ${baseurl%/}/$dlpath" to "${cached}/$dlpath"
wget "${baseurl%/}/$dlpath" -O "$cached/${dlpath}.$$" &&
mv "$cached/$dlpath.$$" "$cached/$dlpath" || {
rm -f "$cached/$dlpath.$$";
error "failed to download $dlpath";
return 1;
}
_RET="$cached/$dlpath"
}
create_main() {
local short_opts="a:hn:p:S:uvV"
local long_opts="arch:,auth-key:,name:,path:,tarball:,userdata:,verbose,version:,rootfs:,mapped-uid:,mapped-gid:"
local getopt_out=""
getopt_out=$(getopt --name "${0##*/}" \
--options "${short_opts}" --long "${long_opts}" -- "$@") &&
eval set -- "${getopt_out}" ||
{ bad_Usage; return; }
local arch="${DEF_ARCH}" dsource="${DEF_SOURCE}" version="${DEF_VERSION}"
local authkey_f="" authkeys="" userdata_f="" path="" tarball=""
local cur="" next=""
local rootfs_d=""
while [ $# -ne 0 ]; do
cur=$1; next=$2;
case "$cur" in
-a|--arch) arch="$next"; shift;;
-h|--help) Usage ; return 0;;
-n|--name) name="$next"; shift;;
-v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
-S|--auth-key) authkey_f="$next"; shift;;
-p|--path) path=$next; shift;;
-v|--version) version=$next; shift;;
-u|--userdata) userdata_f="$next"; shift;;
--tarball) tarball="$next"; shift;;
--source) dsource="$next"; shift;;
--rootfs) rootfs_d="$next"; shift;;
--mapped-uid) LXC_MAPPED_UID=$next; shift;;
--mapped-gid) LXC_MAPPED_GID=$next; shift;;
--) shift; break;;
esac
shift;
done
[ -n "$rootfs_d" ] || rootfs_d="$path/rootfs"
[ $# -eq 0 ] || { bad_Usage "unexpected arguments: $*"; return; }
[ -n "$path" ] || { error "'path' parameter is required"; return 1; }
if [ "$(id -u)" != "0" ]; then
{ error "must be run as root"; return 1; }
fi
case "$arch" in
i?86) arch="i386";;
amd64) arch="x86_64";;
esac
inargs "$arch" "${ARCHES[@]}" ||
{ error "bad arch '$arch'. allowed: ${ARCHES[*]}"; return 1; }
inargs "$dsource" "${SOURCES[@]}" ||
{ error "bad source '$dsource'. allowed: ${SOURCES[*]}"; return 1; }
if [ "$dsource" = "none" ] && [ -n "$userdata_f" -o -n "$authkey_f" ]; then
error "userdata and authkey are incompatible with --source=none";
return 1;
fi
if [ -n "$authkey_f" ]; then
if [ ! -f "$authkey_f" ]; then
error "--auth-key=${authkey_f} must reference a file"
return 1
fi
authkeys=$(cat "$authkey_f") ||
{ error "failed to read ${authkey_f}"; return 1; }
fi
if [ -n "$userdata_f" -a ! -f "${userdata_f}" ]; then
error "${userdata_f}: --userdata arg not a file"
return 1
fi
if [ -z "$tarball" ]; then
if inargs "$version" "${STREAMS[@]}"; then
out=$(wget -O - -q "${DOWNLOAD_URL%/}/version/$version") ||
{ error "failed to convert 'version=$version'"; return 1; }
version="$out"
fi
download_tarball "$arch" "$version" "${CACHE_D}" "${DOWNLOAD_URL}" ||
return
tarball="$_RET"
fi
extract_rootfs "${tarball}" "${rootfs_d}" || return
if [ "$version" = "0.3.2~pre1" ]; then
debug 1 "fixing console for lxc and '$version'"
sed -i 's,^\(#console.* 115200 \)# /dev/console,\1 console,g' \
"$rootfs_d/etc/inittab" ||
{ error "failed to fix console entry for $version"; return 1; }
fi
if [ "$dsource" != "none" ]; then
insert_ds "$dsource" "$path/rootfs" "$authkeys" "$userdata_f" || {
error "failed to insert userdata to $path/rootfs"
return 1
}
fi
copy_configuration "$path" "$path/rootfs" "$name" "$arch" "$release"
return
}
create_main "$@"
# vi: ts=4 expandtab

824
templates/lxc-debian.in Normal file
View File

@ -0,0 +1,824 @@
#!/bin/bash
#
# lxc: linux Container library
# Authors:
# Daniel Lezcano <daniel.lezcano@free.fr>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# Detect use under userns (unsupported)
for arg in "$@"; do
[ "$arg" = "--" ] && break
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
echo "This template can't be used for unprivileged containers." 1>&2
echo "You may want to try the \"download\" template instead." 1>&2
exit 1
fi
done
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
export GREP_OPTIONS=""
MIRROR=${MIRROR:-http://deb.debian.org/debian}
SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.debian.org/}
LOCALSTATEDIR="@LOCALSTATEDIR@"
LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
# Allows the lxc-cache directory to be set by environment variable
LXC_CACHE_PATH=${LXC_CACHE_PATH:-"$LOCALSTATEDIR/cache/lxc"}
find_interpreter()
{
given_interpreter=$(basename "$1")
if [ ! -d /proc/sys/fs/binfmt_misc/ ] ; then
return 1
fi
for file in /proc/sys/fs/binfmt_misc/* ; do
if [ "$file" = "/proc/sys/fs/binfmt_misc/register" -o \
"$file" = "/proc/sys/fs/binfmt_misc/status" ] ; then
continue
fi
interpreter_path=$(sed -n "/^interpreter/s/interpreter \([^[:space:]]*\)/\1/p" "$file")
interpreter=$(basename "$interpreter_path")
if [ "$given_interpreter" = "$interpreter" ] ; then
echo "$interpreter_path"
return 0
fi
done
return 1
}
configure_debian()
{
rootfs=$1
hostname=$2
num_tty=$3
# squeeze only has /dev/tty and /dev/tty0 by default,
# therefore creating missing device nodes for tty1-4.
for tty in $(seq 1 "$num_tty"); do
if [ ! -e "$rootfs/dev/tty$tty" ]; then
mknod "$rootfs/dev/tty$tty" c 4 "$tty"
fi
done
# configure the inittab
cat <<EOF > $rootfs/etc/inittab
id:3:initdefault:
si::sysinit:/etc/init.d/rcS
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin
1:2345:respawn:/sbin/getty 38400 console
$(for tty in $(seq 1 "$num_tty"); do echo "c${tty}:12345:respawn:/sbin/getty 38400 tty${tty} linux" ; done;)
p6::ctrlaltdel:/sbin/init 6
p0::powerfail:/sbin/init 0
EOF
# symlink mtab
[ -e "$rootfs/etc/mtab" ] && rm "$rootfs/etc/mtab"
ln -s /proc/self/mounts "$rootfs/etc/mtab"
# disable selinux in debian
mkdir -p "$rootfs/selinux"
echo 0 > "$rootfs/selinux/enforce"
# configure the network using the dhcp
cat <<EOF > $rootfs/etc/network/interfaces
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
EOF
# set the hostname
cat <<EOF > $rootfs/etc/hostname
$hostname
EOF
# reconfigure some services
# but first reconfigure locales - so we get no noisy perl-warnings
if [ -z "$LANG" ] || echo $LANG | grep -E -q "^C(\..+)*$"; then
cat >> "$rootfs/etc/locale.gen" << EOF
en_US.UTF-8 UTF-8
EOF
chroot "$rootfs" locale-gen en_US.UTF-8 UTF-8
chroot "$rootfs" update-locale LANG=en_US.UTF-8
else
encoding=$(echo "$LANG" | cut -d. -f2)
chroot "$rootfs" sed -e "s/^# \(${LANG} ${encoding}\)/\1/" \
-i /etc/locale.gen 2> /dev/null
cat >> "$rootfs/etc/locale.gen" << EOF
$LANG $encoding
EOF
chroot "$rootfs" locale-gen "$LANG" "$encoding"
chroot "$rootfs" update-locale LANG="$LANG"
fi
# remove pointless services in a container
chroot "$rootfs" /usr/sbin/update-rc.d -f checkroot.sh disable
chroot "$rootfs" /usr/sbin/update-rc.d -f umountfs disable
chroot "$rootfs" /usr/sbin/update-rc.d -f hwclock.sh disable
chroot "$rootfs" /usr/sbin/update-rc.d -f hwclockfirst.sh disable
# generate new SSH keys
if [ -x "$rootfs/var/lib/dpkg/info/openssh-server.postinst" ]; then
cat > "$rootfs/usr/sbin/policy-rc.d" << EOF
#!/bin/sh
exit 101
EOF
chmod +x "$rootfs/usr/sbin/policy-rc.d"
if [ -f "$rootfs/etc/init/ssh.conf" ]; then
mv "$rootfs/etc/init/ssh.conf" "$rootfs/etc/init/ssh.conf.disabled"
fi
rm -f "$rootfs/etc/ssh/"ssh_host_*key*
DPKG_MAINTSCRIPT_PACKAGE=openssh DPKG_MAINTSCRIPT_NAME=postinst chroot "$rootfs" /var/lib/dpkg/info/openssh-server.postinst configure
sed -i "s/root@$(hostname)/root@$hostname/g" "$rootfs/etc/ssh/"ssh_host_*.pub
if [ -f "$rootfs/etc/init/ssh.conf.disabled" ]; then
mv "$rootfs/etc/init/ssh.conf.disabled" "$rootfs/etc/init/ssh.conf"
fi
rm -f "$rootfs/usr/sbin/policy-rc.d"
fi
# set initial timezone as on host
if [ -f /etc/timezone ]; then
cat /etc/timezone > "$rootfs/etc/timezone"
chroot "$rootfs" dpkg-reconfigure -f noninteractive tzdata
elif [ -f /etc/sysconfig/clock ]; then
. /etc/sysconfig/clock
echo "$ZONE" > "$rootfs/etc/timezone"
chroot "$rootfs" dpkg-reconfigure -f noninteractive tzdata
else
echo "Timezone in container is not configured. Adjust it manually."
fi
if [ -n "$authkey" ]; then
local ssh_dir_path="${rootfs}/root/.ssh"
mkdir -p "$ssh_dir_path"
cp "$authkey" "${ssh_dir_path}/authorized_keys"
chmod 700 "$ssh_dir_path"
echo "Inserted SSH public key from '$authkey' into /root/.ssh/authorized_keys"
fi
return 0
}
write_sourceslist()
{
local rootfs="$1"; shift
local release="$1"; shift
local arch="$1"; shift
local prefix="deb"
if [ -n "${arch}" ]; then
prefix="deb [arch=${arch}]"
fi
if [ "$mainonly" = 1 ]; then
non_main=''
else
non_main=' contrib non-free'
fi
cat >> "${rootfs}/etc/apt/sources.list" << EOF
${prefix} $MIRROR ${release} main${non_main}
EOF
if [ "$release" != "unstable" -a "$release" != "sid" ]; then
cat >> "${rootfs}/etc/apt/sources.list" << EOF
${prefix} $SECURITY_MIRROR ${release}/updates main${non_main}
EOF
fi
}
install_packages()
{
local rootfs="$1"; shift
local packages="$*"
chroot "${rootfs}" apt-get update
if [ -n "${packages}" ]; then
chroot "${rootfs}" apt-get install --force-yes -y --no-install-recommends ${packages}
fi
}
configure_debian_systemd()
{
path=$1
rootfs=$2
config=$3
num_tty=$4
# just in case systemd is not installed
mkdir -p "${rootfs}/lib/systemd/system"
mkdir -p "${rootfs}/etc/systemd/system/getty.target.wants"
# Fix getty-static-service as debootstrap does not install dbus
if [ -e "$rootfs//lib/systemd/system/getty-static.service" ] ; then
local tty_services
tty_services=$(for i in $(seq 2 "$num_tty"); do echo -n "getty@tty${i}.service "; done; )
sed 's/ getty@tty.*/'" $tty_services "'/g' \
"$rootfs/lib/systemd/system/getty-static.service" | \
sed 's/\(tty2-tty\)[5-9]/\1'"${num_tty}"'/g' > "$rootfs/etc/systemd/system/getty-static.service"
fi
# This function has been copied and adapted from lxc-fedora
rm -f "${rootfs}/etc/systemd/system/default.target"
chroot "${rootfs}" ln -s /dev/null /etc/systemd/system/udev.service
chroot "${rootfs}" ln -s /dev/null /etc/systemd/system/systemd-udevd.service
chroot "${rootfs}" ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
# Setup getty service on the ttys we are going to allow in the
# default config. Number should match lxc.tty.max
( cd "${rootfs}/etc/systemd/system/getty.target.wants"
for i in $(seq 1 "$num_tty") ; do ln -sf ../getty\@.service getty@tty"${i}".service; done )
# Since we use static-getty.target; we need to mask container-getty@.service generated by
# container-getty-generator, so we don't get multiple instances of agetty running.
# See https://github.com/lxc/lxc/issues/520 and https://github.com/lxc/lxc/issues/484
( cd "${rootfs}/etc/systemd/system/getty.target.wants"
for i in $(seq 0 "$num_tty"); do ln -sf /dev/null container-getty\@"${i}".service; done )
return 0
}
# Check if given path is in a btrfs partition
is_btrfs()
{
[ -e "$1" -a "$(stat -f -c '%T' "$1")" = "btrfs" ]
}
# Check if given path is the root of a btrfs subvolume
is_btrfs_subvolume()
{
[ -d "$1" -a "$(stat -f -c '%T' "$1")" = "btrfs" -a "$(stat -c '%i' "$1")" -eq 256 ]
}
try_mksubvolume()
{
path=$1
[ -d "$path" ] && return 0
mkdir -p "$(dirname "$path")"
if which btrfs >/dev/null 2>&1 && is_btrfs "$(dirname "$path")"; then
btrfs subvolume create "$path"
else
mkdir -p "$path"
fi
}
try_rmsubvolume()
{
path=$1
[ -d "$path" ] || return 0
if which btrfs >/dev/null 2>&1 && is_btrfs_subvolume "$path"; then
btrfs subvolume delete "$path"
else
rm -rf "$path"
fi
}
cleanup()
{
try_rmsubvolume "$cache/partial-$release-$arch"
try_rmsubvolume "$cache/rootfs-$release-$arch"
}
download_debian()
{
case "$release" in
wheezy)
init=sysvinit
iproute=iproute
;;
*)
init=init
iproute=iproute2
;;
esac
packages=\
$init,\
ifupdown,\
locales,\
dialog,\
isc-dhcp-client,\
netbase,\
net-tools,\
$iproute,\
openssh-server
cache=$1
arch=$2
release=$3
interpreter="$4"
interpreter_path="$5"
trap cleanup EXIT SIGHUP SIGINT SIGTERM
# Create the cache
mkdir -p "$cache"
# If debian-archive-keyring isn't installed, fetch GPG keys directly
releasekeyring=/usr/share/keyrings/debian-archive-keyring.gpg
if [ ! -f $releasekeyring ]; then
releasekeyring="$cache/archive-key.gpg"
case $release in
"wheezy")
gpgkeyname="archive-key-7.0"
;;
*)
gpgkeyname="archive-key-8"
;;
esac
wget https://ftp-master.debian.org/keys/${gpgkeyname}.asc -O - --quiet \
| gpg --import --no-default-keyring --keyring="${releasekeyring}"
fi
# check the mini debian was not already downloaded
try_mksubvolume "$cache/partial-$release-$arch"
if [ $? -ne 0 ]; then
echo "Failed to create '$cache/partial-$release-$arch' directory"
return 1
fi
# download a mini debian into a cache
echo "Downloading debian minimal ..."
if [ "$interpreter" = "" ] ; then
debootstrap --verbose --variant=minbase --arch="$arch" \
--include=$packages --keyring="${releasekeyring}" \
"$release" "$cache/partial-$release-$arch" "$MIRROR"
if [ $? -ne 0 ]; then
echo "Failed to download the rootfs, aborting."
return 1
fi
else
debootstrap --foreign --verbose --variant=minbase --arch="$arch" \
--include=$packages --keyring="${releasekeyring}" \
"$release" "$cache/partial-$release-$arch" "$MIRROR"
if [ $? -ne 0 ]; then
echo "Failed to download the rootfs, aborting."
return 1
fi
mkdir -p "$(basename "$cache/partial-$release-$arch/$interpreter_path")"
cp "$interpreter" "$cache/partial-$release-$arch/$interpreter_path"
if [ $? -ne 0 ]; then
echo "failed to copy $interpreter to $cache/partial-$release-$arch/$interpreter_path"
return 1
fi
chroot "$cache/partial-$release-$arch" debootstrap/debootstrap --second-stage
if [ $? -ne 0 ]; then
echo "failed to update the rootfs, aborting"
return 1
fi
fi
mv "$1/partial-$release-$arch" "$1/rootfs-$release-$arch"
echo "Download complete."
trap EXIT
trap SIGINT
trap SIGTERM
trap SIGHUP
return 0
}
copy_debian()
{
cache=$1
arch=$2
rootfs=$3
release=$4
# make a local copy of the minidebian
echo -n "Copying rootfs to $rootfs..."
try_mksubvolume "$rootfs"
if which btrfs >/dev/null 2>&1 && \
is_btrfs_subvolume "$cache/rootfs-$release-$arch" && \
is_btrfs_subvolume "$rootfs"; then
realrootfs="$(dirname "$config")"/rootfs
[ "$rootfs" = "$realrootfs" ] || umount "$rootfs" || return 1
btrfs subvolume delete "$realrootfs" || return 1
btrfs subvolume snapshot "$cache/rootfs-$release-$arch" "$realrootfs" || return 1
[ "$rootfs" = "$realrootfs" ] || mount --bind "$realrootfs" "$rootfs" || return 1
else
rsync -SHaAX "$cache/rootfs-$release-$arch"/ $rootfs/ || return 1
fi
return 0
}
install_debian()
{
rootfs=$1
release=$2
arch=$3
cache="$4/debian"
interpreter="$5"
interpreter_path="$6"
flushcache=$7
mkdir -p $LOCALSTATEDIR/lock/subsys/
(
flock -x 9
if [ $? -ne 0 ]; then
echo "Cache repository is busy."
return 1
fi
if [ "$flushcache" -eq 1 ]; then
echo "Flushing cache..."
cleanup
fi
echo "Checking cache download in $cache/rootfs-$release-$arch ... "
if [ ! -e "$cache/rootfs-$release-$arch" ]; then
download_debian "$cache" "$arch" "$release" "$interpreter" "$interpreter_path"
if [ $? -ne 0 ]; then
echo "Failed to download 'debian base'"
return 1
fi
fi
copy_debian "$cache" "$arch" "$rootfs" "$release"
if [ $? -ne 0 ]; then
echo "Failed to copy rootfs"
return 1
fi
return 0
) 9>$LOCALSTATEDIR/lock/subsys/lxc-debian
return $?
}
copy_configuration()
{
path=$1
rootfs=$2
hostname=$3
arch=$4
num_tty=$5
# Generate the configuration file
# if there is exactly one veth network entry, make sure it has an
# associated hwaddr.
nics=$(grep -ce '^lxc\.net\.0\.type[ \t]*=[ \t]*veth' "$path/config")
if [ "$nics" -eq 1 ]; then
grep -q "^lxc.net.0.hwaddr" "$path/config" || sed -i -e "/^lxc\.net\.0\.type[ \t]*=[ \t]*veth/a lxc.net.0.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" "$path/config"
fi
## Add all the includes
echo "" >> "$path/config"
echo "# Common configuration" >> "$path/config"
if [ -e "${LXC_TEMPLATE_CONFIG}/debian.common.conf" ]; then
echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/debian.common.conf" >> "$path/config"
fi
if [ -e "${LXC_TEMPLATE_CONFIG}/debian.${release}.conf" ]; then
echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/debian.${release}.conf" >> "$path/config"
fi
## Add the container-specific config
echo "" >> "$path/config"
echo "# Container specific configuration" >> "$path/config"
grep -q "^lxc.rootfs.path" "$path/config" 2> /dev/null || echo "lxc.rootfs.path = $rootfs" >> "$path/config"
cat <<EOF >> $path/config
lxc.tty.max = $num_tty
lxc.uts.name = $hostname
lxc.arch = $arch
lxc.pty.max = 1024
EOF
if [ $? -ne 0 ]; then
echo "Failed to add configuration"
return 1
fi
return 0
}
post_process()
{
local rootfs="$1"; shift
local release="$1"; shift
local arch="$1"; shift
local hostarch="$1"; shift
local interpreter="$1"; shift
local packages="$*"
# Disable service startup
cat > "${rootfs}/usr/sbin/policy-rc.d" << EOF
#!/bin/sh
exit 101
EOF
chmod +x "${rootfs}/usr/sbin/policy-rc.d"
# If the container isn't running a native architecture, setup multiarch
if [ "$interpreter" = "" -a "${arch}" != "${hostarch}" ]; then
# Test if dpkg supports multiarch
if ! chroot "$rootfs" dpkg --print-foreign-architectures 2>&1; then
chroot "$rootfs" dpkg --add-architecture "${hostarch}"
fi
fi
# Write a new sources.list containing both native and multiarch entries
> "${rootfs}/etc/apt/sources.list"
if [ "$interpreter" != "" -a "${arch}" = "${hostarch}" ]; then
write_sourceslist "${rootfs}" "${release}" "${arch}"
else
write_sourceslist "${rootfs}" "${release}"
fi
# Install Packages in container
if [ -n "${packages}" ]; then
local pack_list
pack_list="${packages//,/ }"
echo "Installing packages: ${pack_list}"
install_packages "${rootfs}" "${pack_list}"
fi
# Re-enable service startup
rm "${rootfs}/usr/sbin/policy-rc.d"
# end
}
clean()
{
cache=${LXC_CACHE_PATH:-"$LOCALSTATEDIR/cache/lxc/debian"}
if [ ! -e "$cache" ]; then
exit 0
fi
# lock, so we won't purge while someone is creating a repository
(
flock -x 9
if [ $? != 0 ]; then
echo "Cache repository is busy."
exit 1
fi
echo -n "Purging the download cache..."
rm --preserve-root --one-file-system -rf "$cache" && echo "Done." || exit 1
exit 0
) 9>$LOCALSTATEDIR/lock/subsys/lxc-debian
}
usage()
{
cat <<EOF
Template specific options can be passed to lxc-create after a '--' like this:
lxc-create --name=NAME [-lxc-create-options] -- [-template-options]
Usage: $1 -h|--help -p|--path=<path> [-c|--clean] [-a|--arch=<arch>] [-r|--release=<release>]
[--mirror=<mirror>] [--security-mirror=<security mirror>]
[--package=<package_name1,package_name2,...>]
[-I|--interpreter-path=<interpreter path>]
[-F | --flush-cache] [-S|--auth-key=<keyfile>]
Options :
-h, --help print this help text
-p, --path=PATH directory where config and rootfs of this VM will be kept
-S, --auth-key=KEYFILE SSH public key to inject into the container as the root user.
-a, --arch=ARCH The container architecture. Can be one of: i686, x86_64,
amd64, armhf, armel, powerpc. Defaults to host arch.
-r, --release=RELEASE Debian release. Can be one of: wheezy, jessie, stretch, buster, sid.
Defaults to current stable.
--mirror=MIRROR Debian mirror to use during installation. Overrides the MIRROR
environment variable (see below).
--security-mirror=SECURITY_MIRROR
Debian mirror to use for security updates. Overrides the
SECURITY_MIRROR environment variable (see below).
--packages=PACKAGE_NAME1,PACKAGE_NAME2,...
List of additional packages to install. Comma separated, without space.
-c, --clean only clean up the cache and terminate
--enable-non-free include also Debian's contrib and non-free repositories.
-I|--interpreter-path=INTERPRETER-PATH
Path of the binfmt interpreter to copy to the rootfs
-F | --flush-cache Flush the debian release cache
Environment variables:
MIRROR The Debian package mirror to use. See also the --mirror switch above.
Defaults to '$MIRROR'
SECURITY_MIRROR The Debian package security mirror to use. See also the --security-mirror switch above.
Defaults to '$SECURITY_MIRROR'
EOF
return 0
}
options=$(getopt -o hp:n:a:r:cI:FS: -l arch:,auth-key:,clean,help,enable-non-free,mirror:,name:,packages:,path:,release:,rootfs:,security-mirror:,interpreter-path:,flush-cache -- "$@")
if [ $? -ne 0 ]; then
usage "$(basename "$0")"
exit 1
fi
eval set -- "$options"
littleendian=$(lscpu | grep '^Byte Order' | grep -q Little && echo yes)
arch=$(uname -m)
if [ "$arch" = "i686" ]; then
arch="i386"
elif [ "$arch" = "x86_64" ]; then
arch="amd64"
elif [ "$arch" = "armv7l" ]; then
arch="armhf"
elif [ "$arch" = "aarch64" ]; then
arch="arm64"
elif [ "$arch" = "ppc" ]; then
arch="powerpc"
elif [ "$arch" = "ppc64le" ]; then
arch="ppc64el"
elif [ "$arch" = "mips" -a "$littleendian" = "yes" ]; then
arch="mipsel"
elif [ "$arch" = "mips64" -a "$littleendian" = "yes" ]; then
arch="mips64el"
fi
hostarch=$arch
mainonly=1
flushcache=0
while true
do
case "$1" in
-h|--help) usage "$0" && exit 1;;
--) shift 1; break ;;
-a|--arch) arch=$2; shift 2;;
-S|--auth-key) authkey=$2; shift 2;;
-I|--interpreter-path)
interpreter="$2"; shift 2;;
-c|--clean) clean=1; shift 1;;
--enable-non-free) mainonly=0; shift 1;;
--mirror) MIRROR=$2; shift 2;;
-n|--name) name=$2; shift 2;;
--packages) packages=$2; shift 2;;
-p|--path) path=$2; shift 2;;
-r|--release) release=$2; shift 2;;
--rootfs) rootfs=$2; shift 2;;
--security-mirror) SECURITY_MIRROR=$2; shift 2;;
-F|--flush-cache) flushcache=1; shift 1;;
*) break ;;
esac
done
if [ ! -z "$clean" -a -z "$path" ]; then
clean || exit 1
exit 0
fi
if [ "$arch" = "i686" ]; then
arch=i386
fi
if [ "$arch" = "x86_64" ]; then
arch=amd64
fi
if [ "$interpreter" = "" ] ; then
if [ $hostarch = "i386" -a $arch = "amd64" ]; then
echo "can't create $arch container on $hostarch"
exit 1
fi
if [ $hostarch = "armhf" -o $hostarch = "armel" ] && \
[ $arch != "armhf" -a $arch != "armel" ]; then
echo "can't create $arch container on $hostarch"
exit 1
fi
if [ $hostarch = "powerpc" -a $arch != "powerpc" ]; then
echo "can't create $arch container on $hostarch"
exit 1
fi
if [ $hostarch = "mips" -a $arch != "mips" ] || \
[ $hostarch = "mipsel" -a $arch != "mipsel" ] || \
[ $hostarch = "mips64" -a $arch != "mips" -a $arch != "mips64" ] || \
[ $hostarch = "mips64el" -a $arch != "mipsel" -a $arch != "mips64el" ]; then
echo "can't create $arch container on $hostarch"
exit 1
fi
else
if ! file -b "${interpreter}" |grep -q "statically linked" ; then
echo "'${interpreter}' must be statically linked" 1>&2
exit 1
fi
interpreter_path=$(find_interpreter "$interpreter")
if [ $? -ne 0 ] ; then
echo "no binfmt interpreter using $(basename "$interpreter")" 1>&2
exit 1
fi
fi
type debootstrap
if [ $? -ne 0 ]; then
echo "'debootstrap' command is missing"
exit 1
fi
if [ -z "$path" ]; then
echo "'path' parameter is required"
exit 1
fi
if [ "$(id -u)" != "0" ]; then
echo "This script should be run as 'root'"
exit 1
fi
if [ -n "$authkey" ]; then
if [ ! -f "$authkey" ]; then
echo "SSH keyfile '$authkey' not found"
exit 1
fi
# This is mostly to prevent accidental uage of the private key instead
# of the public key.
if [ "${authkey: -4}" != ".pub" ]; then
echo "SSH keyfile '$authkey' does not end with '.pub'"
exit 1
fi
fi
release=${release:-stable}
permanent_releases=('stable' 'testing' 'sid' 'unstable')
if [[ ! "${permanent_releases[*]}" =~ (^|[^[:alpha:]])$release([^[:alpha:]]|$) ]]; then
if ! wget "${MIRROR}/dists/${release}/Release" -O /dev/null 2> /dev/null; then
echo "Invalid release ${release} (not found in mirror)"
exit 1
fi
fi
# detect rootfs
config="$path/config"
if [ -z "$rootfs" ]; then
if grep -q '^lxc.rootfs.path' "$config" 2> /dev/null ; then
rootfs=$(awk -F= '/^lxc.rootfs.path[ \t]+=/{ print $2 }' "$config")
else
rootfs=$path/rootfs
fi
fi
# determine the number of ttys - default is 4
if grep -q '^lxc.tty.max' "$config" 2> /dev/null ; then
num_tty=$(awk -F= '/^lxc.tty.max[ \t]+=/{ print $2 }' "$config")
else
num_tty=4
fi
install_debian "$rootfs" "$release" "$arch" "$LXC_CACHE_PATH" "$interpreter" "$interpreter_path" "$flushcache"
if [ $? -ne 0 ]; then
echo "failed to install debian"
exit 1
fi
configure_debian "$rootfs" "$name" $num_tty
if [ $? -ne 0 ]; then
echo "failed to configure debian for a container"
exit 1
fi
copy_configuration "$path" "$rootfs" "$name" $arch $num_tty
if [ $? -ne 0 ]; then
echo "failed write configuration file"
exit 1
fi
configure_debian_systemd "$path" "$rootfs" "$config" $num_tty
post_process "${rootfs}" "${release}" ${arch} ${hostarch} "${interpreter}" "${packages}"
if [ ! -z "$clean" ]; then
clean || exit 1
exit 0
fi

File diff suppressed because it is too large Load Diff

1291
templates/lxc-fedora.in Normal file

File diff suppressed because it is too large Load Diff

833
templates/lxc-gentoo.in Normal file
View File

@ -0,0 +1,833 @@
#!/bin/bash
#
# LXC template for gentoo
#
# Author: Guillaume Zitta <lxc@zitta.fr>
#
# Widely inspired from lxc-gentoo script at https://github.com/globalcitizen/lxc-gentoo
#
# this version is reworked with :
# - out of the lxc-create compat
# - vanilla gentoo config
# - ready to use cache
#
# Detect use under userns (unsupported)
for arg in "$@"; do
[ "$arg" = "--" ] && break
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
echo "This template can't be used for unprivileged containers." 1>&2
echo "You may want to try the \"download\" template instead." 1>&2
exit 1
fi
done
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
# Ensure strict root's umask doesen't render the VM unusable
umask 022
LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
################################################################################
# Various helper functions
################################################################################
# param: $1: the name of the lock
# param: $2: the timeout for the lock
# The rest contain the command to execute and its parameters
execute_exclusively()
{
mkdir -p @LOCALSTATEDIR@/lock/subsys/
local lock_name="$1"
local timeout="$2"
shift 2
{
printf "Attempting to obtain an exclusive lock (timeout: %s sec) named \"%s\"...\n" "${timeout}" "$lock_name"
flock -x -w "${timeout}" 50
if [[ $? -ne 0 ]]; then
printf " => unable to obtain lock, aborting.\n"
return 2
else
printf " => done.\n"
fi
printf " => Executing \"%s\"\n" "$*"
"$@"
retval=$?
} 50> "@LOCALSTATEDIR@/lock/subsys/lxc-gentoo-${lock_name}"
return $retval
}
# a die function is always a good idea
die()
{
printf "\n[the last exit code leading to this death was: %s ]\n" "$?"
local retval="$1"
shift 1
printf "$@"
exit "$retval"
}
# gentoo arch/variant detection
set_default_arch()
{
printf "### set_default_arch: default arch/variant autodetect...\n"
arch=$(uname -m)
if [[ $arch =~ i.86 ]]; then
arch="x86"
variant="x86"
elif [[ $arch == "x86_64" ]]; then
arch="amd64"
variant="amd64"
elif [[ $arch =~ arm.* ]]; then
arch="arm"
variant="armv7a"
else
#who knows, it may work...
printf " => warn: unexpected arch:${arch} let me knows if it works :)\n"
variant="${arch}"
fi
printf " => Got: arch=%s variant=%s\n" "${arch}" "${variant}"
}
store_user_message()
{
user_message="${user_message}=> $@\n"
}
################################################################################
# CACHE Preparation
################################################################################
# during setup cachedir is $cacheroot/partial-$arch-$variant
# at the end, it will be $cacheroot/rootfs-$arch-$variant
cache_setup(){
partialfs="${cacheroot}/partial-${arch}-${variant}"
#if cache exists and flush not needed, return
[[ -d "${cachefs}" && -z "${flush_cache}" ]] && return 0
printf "###### cache_setup(): doing cache preparation\n"
local retval=1
#clean from failed previous run
rm -rf "${partialfs}"
mkdir -p "${partialfs}"
#let's go
cache_precheck && \
cache_stage3 && \
cache_portage && \
cache_inittab && \
cache_net && \
cache_dev && \
cache_openrc && \
cache_locale && \
rm -rf "${cachefs}" && \
mv "${partialfs}" "${cachefs}" && \
printf "###### cache_setup: Cache should be ready\n"
return $?
}
cache_precheck()
{
printf "### cache_precheck(): doing some pre-start checks ...\n"
# never hurts to have a fail-safe.
[[ -n "${cacheroot//\/}" ]] \
|| die 8 "\$cacheroot (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${cacheroot}"
}
#get latest stage3 tarball
cache_stage3()
{
printf "### cache_stage3(): stage3 cache deployment...\n"
if [ -z "${tarball}" ]; then
#variables init
local stage3_baseurl="${mirror}/releases/${arch}/autobuilds"
# get latest-stage3....txt file for subpath
local stage3_pointer="${stage3_baseurl}/latest-stage3-${variant}.txt"
printf "Determining path to latest Gentoo %s (%s) stage3 archive...\n" "${arch}" "${variant}"
printf " => downloading and processing %s\n" "${stage3_pointer}"
local stage3_latest_tarball=$(wget -q -O - "${stage3_pointer}" | tail -n1 | cut -d' ' -f1) \
|| die 6 "Error: unable to fetch\n"
printf " => Got: %s\n" "${stage3_latest_tarball}"
printf "Downloading/untarring the actual stage3 tarball...\n"
compressor="j"
if echo ${stage3_latest_tarball} | grep ".xz$"; then
compressor="J"
fi
wget -O - "${stage3_baseurl}/${stage3_latest_tarball}" \
| tar -x${compressor}pf - --numeric-owner -C "${partialfs}" \
|| die 6 "Error: unable to fetch or untar\n"
printf " => extracted to: %s\n" "${partialfs}"
else
printf "Extracting the stage3 tarball...\n"
tar -xpf "${tarball}" --numeric-owner -C "${partialfs}" \
|| die 6 "unable to untar ${tarball} to ${partialfs}"
fi
#check if it chroots
printf "chroot test..."
chroot ${partialfs} /bin/true || die 1 "Error: chroot %s /bin/true, failed" "${partialfs}"
printf " OK\n"
printf " => stage3 cache extracted in : %s\n" "${partialfs}"
return 0
}
cache_portage()
{
printf "### cache_portage: caching portage tree tarball...\n"
[[ -z "${flush_cache}" && -f "${portage_cache}" ]] && return 0
rm -f ${portage_cache}
printf "Downloading Gentoo portage (software build database) snapshot...\n"
execute_exclusively portage 60 wget -O "${portage_cache}" "${mirror}/snapshots/portage-latest.tar.bz2" \
|| die 6 "Error: unable to fetch\n"
printf " => done.\n"
}
# custom inittab
cache_inittab()
{
printf "### cache_inittab: tuning inittab...\n"
INITTAB="${partialfs}/etc/inittab"
[[ -w "$INITTAB" ]] || die 1 "Error: $INITTAB is not writeable"
# create console
echo "# Lxc main console" >> "$INITTAB"
echo "1:12345:respawn:/sbin/agetty -a root --noclear 115200 console linux" >> "$INITTAB"
# finally we add a pf line to enable clean shutdown on SIGPWR (issue 60)
echo "# clean container shutdown on SIGPWR" >> "$INITTAB"
echo "pf:12345:powerwait:/sbin/halt" >> "$INITTAB"
# we also blank out /etc/issue here in order to prevent delays spawning login
# caused by attempts to determine domainname on disconnected containers
sed -i 's/[\][Oo]//g' "${partialfs}/etc/issue"
}
cache_net()
{
printf "### cache_net: doing some useful net tuning...\n"
# useful for chroot
# /etc/resolv.conf
grep -i 'search ' /etc/resolv.conf > "${partialfs}/etc/resolv.conf"
grep -i 'nameserver ' /etc/resolv.conf >> "${partialfs}/etc/resolv.conf"
# fix boot-time interface config wipe under aggressive cap drop
# (openrc 0.9.8.4 ~sep 2012 - https://bugs.gentoo.org/show_bug.cgi?id=436266)
# initial warkaround was: sed -i -e 's/^#rc_nostop=""/rc_nostop="net.eth0 net.lo"/' "${partialfs}/etc/rc.conf"
# but this one does not depends on interfaces names
echo 'rc_keyword="-stop"' >> "${partialfs}/etc/conf.d/net"
}
cache_dev()
{
printf "### cache_dev(): /dev tuning...\n"
#Wait for https://bugs.gentoo.org/show_bug.cgi?id=496054
mkdir "${partialfs}/dev/pts"
mkdir "${partialfs}/dev/shm"
mkdir "${partialfs}/dev/mqueue"
mkdir -m 755 "${partialfs}/dev/net"
mknod -m 666 "${partialfs}/dev/net/tun" c 10 200
return 0
}
# fix openrc system
cache_openrc()
{
printf "### cache_openrc(): doing openrc tuning\n"
#Wait for https://bugs.gentoo.org/show_bug.cgi?id=496054
chroot "${partialfs}" sed s/-lxc//g -i "/etc/init.d/devfs"
return 0
}
cache_locale()
{
printf "### cache_locale(): initiating minimale locale en_US.UTF-8 \n"
echo "en_US.UTF-8 UTF-8" >> "${partialfs}/etc/locale.gen"
chroot "${partialfs}" locale-gen
return 0
}
################################################################################
# CONTAINER Preparation
################################################################################
container_setup() {
printf "##### container_setup(): starting container setup\n"
#in most cases lxc-create should have provided a copy of default lxc.conf
#let's tag where template starts, or just create the files
echo '### lxc-gentoo template stuff starts here' >> "$path/config"
#Determine rootfs
#If backingstore was specified, lxc.rootfs.path should be present or --rootfs did the rootfs var creation
if [ -z "${rootfs}" ]; then
rootfs=`awk -F= '$1 ~ /^lxc.rootfs.path/ { print $2 }' "$path/config" 2>/dev/null`
if [ -z "${rootfs}" ]; then
#OK it's default
rootfs="${path}/rootfs"
fi
fi
store_user_message "rootfs of container is : ${rootfs}"
store_user_message "config of container is : ${path}/config"
container_precheck && \
container_rootfs && \
container_consoles && \
container_tz && \
container_portage && \
container_net && \
container_hostname && \
container_auth && \
container_sshd && \
container_conf
if [ $? -ne 0 ]; then
die 1 "container_setup(): one step didn't complete, sorry\n"
fi
printf "###### container_setup(): container should be ready to start!\n"
printf "\n\n"
printf "You could now use you container with: lxc-start -n %s\n" "${name}"
printf "little things you should know about your container:\n"
printf "${user_message}"
return 0
}
container_precheck()
{
printf "### container_precheck(): doing some pre-start checks ...\n"
# never hurts to have a fail-safe.
[[ -n "${name//\/}" ]] \
|| die 8 "\$name (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${name}"
[[ -n "${rootfs//\/}" ]] \
|| die 8 "\$rootfs (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${rootfs}"
[[ -n "${cachefs//\/}" ]] \
|| die 8 "\$cachefs (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPARATORS, THIS IS *VERY* BAD!\n" "${cachefs}"
# check if the rootfs already exists
[[ -d "${rootfs}/etc" ]] && die 18 "Error: \$rootfs (%s) already exists!" "${rootfs}"
# check cache
[[ ! -d "${cachefs}/etc" ]] && die 1 "Error: \$cachefs (%s) not found!" "${cachefs}"
return 0
}
container_rootfs()
{
printf "#### container_rootfs(): copying rootfs %s from cache %s ...\n" "${rootfs}" "${cachefs}"
tar -c -f - --numeric-owner -C "${cachefs}" . \
| tar -x -p -f - --numeric-owner -C "${rootfs}" \
|| die 1 "Error: cache copy to rootfs failed"
printf "chroot test..."
chroot "${rootfs}" /bin/true || die 1 "Error: 'chroot %s /bin/true' failed"
printf " OK\n"
printf " => done\n"
return 0
}
container_consoles() {
printf "#### container_consoles(): setting container consoles ...\n"
# disable unwanted ttys
if [[ ${tty} < 6 ]]; then
local mindis=$(( ${tty} + 1 ))
sed -i "s/^c[${mindis}-6]/#&/" "${rootfs}/etc/inittab"
fi
printf " => main console + ${tty} ttys\n"
if [[ -z "${autologin}" ]]; then
sed 's/agetty -a root/agetty/' -i "${rootfs}/etc/inittab"
elif [[ "${user}" != "root" ]]; then
sed "s/agetty -a root/agetty -a ${user}/" -i "${rootfs}/etc/inittab"
printf " => Autologin on main console for %s enabled\n" "${user}"
[[ -z "${forced_password}" ]] && unset password
store_user_message "${user} has autologin on main console"
else
printf " => Autologin on main console for root enabled\n"
[[ -z "${forced_password}" ]] && unset password
store_user_message "${user} has autologin on main console"
fi
printf " => done\n"
}
container_tz()
{
printf "#### container_tz(): setting container timezone ...\n"
#let's try to copy it from host
if [ -L "/etc/localtime" ]; then
#host has a symlink
#let see if we can reproduct symlink
target=$(readlink /etc/localtime)
if [[ "$target" != "" ]]; then
if [ -f "${rootfs}/${target}" ]; then
#same target exists in container
chroot "${rootfs}" ln -sf "${target}" "/etc/localtime"
printf " => host symlink reproducted in container : %s\n" "${target}"
store_user_message "timezone copyed from host"
return 0
fi
fi
fi
if [ -e /etc/localtime ]; then
# duplicate host timezone
cat /etc/localtime > "${rootfs}/etc/localtime"
printf " => host localtime copyed to container\n"
store_user_message "timezone was staticly copyed from host"
else
# otherwise set up UTC
chroot "${rootfs}" ln -sf /usr/share/zoneinfo/UTC /etc/localtime
printf " => fallback: fixed to UTC\n"
store_user_message "timezone was fixed to UTC"
fi
}
container_portage()
{
printf "#### container_portage(): setting container portage... \n"
#default entry for conf
portage_mount="#container set with private portage tree, no mount here"
printf "Warnings are normal here, don't worry\n"
#container repos detection
if chroot ${rootfs} portageq get_repo_path / gentoo > /dev/null ; then
portage_container="$(chroot ${rootfs} portageq get_repo_path / gentoo)"
else
die 1 "Failed to figure out container portage tree location with portageq get_repo_path / gentoo\n"
fi
if [[ -n "${private_portage}" ]]; then
container_private_portage
return 0
fi
if [ -z "${portage_dir}" ]; then
#gentoo host detection
printf "trying to guess portage_dir from host...\n"
portage_dir="$(portageq get_repo_path / gentoo 2>/dev/null)"
if [ ! -d "${portage_dir}/profiles" ]; then
printf " => host portage detection failed (not gentoo host), fallback to private portage tree\n"
container_private_portage
return 0
fi
else
if [ ! -d "${portage_dir}/profiles" ]; then
die 1 "specified portage_dir (%s) does not contains profiles, is it a portage tree ?\n" "${portage_dir}"
fi
fi
printf "trying to guess portage distfiles dir from host ...\n"
portage_distfiles_dir="$(portageq distdir 2>/dev/null)"
if [ ! -d "${portage_distfiles_dir}" ]; then
portage_distfiles_dir="${portage_dir}/distfiles"
fi
# if we are here, we have shared portage_dir
#ensure dir exists
chroot "${rootfs}" mkdir ${portage_container}
portage_mount="#container set with shared portage
lxc.mount.entry=${portage_dir} ${portage_container/\//} none ro,bind 0 0
lxc.mount.entry=${portage_distfiles_dir} ${portage_container/\//}/distfiles none rw,bind 0 0
#If you use eix, you should uncomment this
#lxc.mount.entry=/var/cache/eix var/cache/eix none ro,bind 0 0"
store_user_message "container has a shared portage from host's ${portage_dir} to ${portage_container/\//}"
#Let's propose binary packages
cat <<- EOF >> "${rootfs}/etc/portage/make.conf"
# enable this to store built binary packages
#FEATURES="\$FEATURES buildpkg"
# enable this to use built binary packages
#EMERGE_DEFAULT_OPTS="\${EMERGE_DEFAULT_OPTS} --usepkg"
# enable and *tune* this kind of entry to slot binaries, specialy if you use multiples archs and variants
#PKGDIR="\${PKGDIR}/amd64
#or PKGDIR="\${PKGDIR}/hardened"
EOF
printf " => portage stuff done, see /etc/portage/make.conf for additional tricks\n"
}
container_private_portage()
{
#called from container_portage() do not call directly from container_setup
printf "# untaring private portage to %s from %s ... \n" "${rootfs}/${portage_container}" "${portage_cache}"
mkdir -p "${rootfs}/${portage_container}"
execute_exclusively portage 60 \
tar -xp --strip-components 1 -C "${rootfs}/${portage_container}" \
-f "${portage_cache}" --numeric-owner \
|| die 2 "Error: unable to extract the portage tree.\n"
store_user_message "container has its own portage tree at ${portage_container}"
printf "=> done\n"
}
#helper func for container_genconf_net()
nic_write()
{
#display with gentoo's confd.net format
echo "config_${nic_name}=\"${nic_conf}\""
#add to managed list
[[ "${nic_conf}" == "dhcp" ]] && nic_managed="${nic_managed} ${nic_name}"
[[ "${nic_conf}" == "null" ]] && nic_unmanaged="${nic_unmanaged} ${nic_name}"
[[ -z "${nic_hwaddr}" && ${nic_type} == "veth" ]] && nic_wo_hwaddr="${nic_wo_hwaddr} ${nic_name}"
nic_writed=1
}
#Analyse lxc.conf and print conf.d/net content
container_conf_net()
{
local file=${1}
[[ -z "${nic_last}" ]] && nic_last=-1
[[ -z "${nic_named}" ]] && nic_named=0
OLDIFS=$IFS
IFS="
"
#let's do some drity bash things to parse lxc network conf
for line in $( sed -r "s/[ ]*=[ ]*/_real_ugly_sep_42_/" "${file}" ); do
key=$(echo "${line}" | sed 's/_real_ugly_sep_42_.*$//')
value=$(echo "${line}" | sed 's/^.*_real_ugly_sep_42_//')
#new nic !
if [[ "${key}" == "lxc.net.0.type" ]]; then
#we don't know what to do with it.
[[ "${value}" == "empty" ]] && continue
#write conf from previous loops
[[ "${nic_writed}" == "0" ]] && nic_write
#init defaults
let nic_last=nic_last+1
nic_writed=0
#if 1 named between 2 not named: last is eth1
#=> Number is ID munis number of named NIC before
nic_name="eth$(( ${nic_last} - ${nic_named} ))"
nic_conf="dhcp"
nic_type="${value}"
fi
if [[ "${key}" == "lxc.net.0.hwaddr" ]]; then
nic_hwaddr=1
fi
if [[ "${key}" =~ ^lxc.net.0.ipv(4|6) ]]; then
#tell openrc to not manage this NIC as LXC set there address
nic_conf="null"
fi
if [[ "${key}" =~ ^lxc.net.0.name ]]; then
nic_name="${value}"
let nic_named=nic_named+1
fi
if [[ "${key}" == "lxc.include" ]]; then
#recursive into include
container_conf_net "${value}"
fi
done
#write conf from previous loops
[[ "${nic_writed}" == "0" ]] && nic_write
IFS=$OLDIFS
}
container_net()
{
printf "container_net(): setting container network conf... \n"
#Analyse network configuration in config
container_conf_net "$path/config" >> "${rootfs}/etc/conf.d/net"
# found how much nic finally have
nic_count=$(( ${nic_last} + 1 ))
# unless openrc manage a nic, we now have to force openrc to automatic
# provision of the 'net' dep. If we do not, network dependent services
# will fail to load
if [[ -z "${nic_managed}" ]]; then
#tell openrc that lxc already did the work
echo 'rc_provide="net"' >> "${rootfs}/etc/rc.conf"
fi
#No NIC ?
if [[ ${nic_count} == 0 ]]; then
#If no Nic, no need to continue
bridge=$(brctl show | awk 'NR==2 {print $1}')
if [[ "${bridge}" != "" ]]; then
store_user_message "No network interface for this container
It's a pitty, you have bridge, ${bridge}.
If it is for Lxc, use it next time by adding this to your default.conf :
lxc.net.0.type = veth
lxc.net.0.link = ${bridge}
lxc.net.0.flags = up
lxc.net.0.hwaddr = fe:xx:xx:xx:xx:xx"
return 0
else
store_user_message "No network interface for this container"
return 0
fi
fi
#For each openrc managed nic, activate
sys_nic_index=1
for nic in ${nic_managed}
do
chroot "${rootfs}" ln -s net.lo "/etc/init.d/net.${nic}"
chroot "${rootfs}" rc-update add net.${nic} default
#fake sysfs for openrc, in case settings does not provide it
mkdir -p "${rootfs}/sys/class/net/${nic}"
echo ${sys_nic_index} > "${rootfs}/sys/class/net/${nic}/ifindex"
echo up > "${rootfs}/sys/class/net/${nic}/operstate"
let sys_nic_index=sys_nic_index+1
done
#Warn about dynamic hwaddr
if [[ -n "${nic_wo_hwaddr}" ]]; then
store_user_message "Warning, these veth NIC don't have fixed hwaddr :
${nic_wo_hwaddr}
see http://lists.linuxcontainers.org/pipermail/lxc-devel/2013-December/006736.html
and man lxc.conf"
fi
printf " => network conf done.\n"
}
# custom hostname
container_hostname()
{
printf "#### container_hostname(): setting hostname... \n"
printf "hostname=\"%s\"\n" "${name}" > "${rootfs}/etc/conf.d/hostname"
printf " => done.\n"
}
container_auth()
{
printf "#### container_auth(): setting authentification... \n"
if [[ "${user}" != "root" ]]; then
printf " non root user requested, creating... \n"
chroot "${rootfs}" useradd --create-home -s /bin/bash "${user}" || die 1 "failed to create user ${user}"
printf " => user %s created\n" "${user}"
fi
store_user_message "Connection user is ${user}"
#Home of user
auth_home=$(chroot "${rootfs}" getent passwd "${user}" | cut -d : -f 6)
if [[ -r "${auth_key}" ]]; then
printf " deploying auth_key %s for user %s ...\n" "${auth_key}" "${user}"
mkdir -p "${rootfs}/${auth_home}/.ssh"
cat "${auth_key}" >> "${rootfs}/${auth_home}/.ssh/authorized_keys"
chroot "${rootfs}" chown "${user}:" "${auth_home}/.ssh/authorized_keys"
printf " => inserted public key in %s/.ssh/authorized_keys\n" "${auth_home}"
[[ -z "${forced_password}" ]] && unset password
store_user_message "${user} has the ssh key you gave us"
fi
if [[ -n "${password}" ]]; then
printf " setting password for %s ...\n" "${user}"
echo "${user}:${password}" | chroot "${rootfs}" chpasswd || die 1 "failed to change password"
printf " => done. if you didn't specify , default is 'toor'\n"
if [[ -n "${forced_password}" ]]; then
store_user_message "${user} has the password you give for him"
fi
fi
printf " => done.\n"
}
container_sshd() {
printf "#### container_sshd(): enabling sshd... \n"
chroot "${rootfs}" rc-update add sshd || die 1 "failed to enable sshd\n"
printf " => done.\n"
}
################################################################################
# lxc configuration files
################################################################################
container_conf()
{
printf "container_configuration(): making lxc configuration file... \n"
#at this point if there
conf_file="${path}/config"
# if there is exactly one veth network entry, make sure it has an
# associated hwaddr.
nics=`grep -e '^lxc\.net\.0\.type[ \t]*=[ \t]*veth' ${conf_file} | wc -l`
if [ $nics -eq 1 ]; then
grep -q "^lxc.net.0.hwaddr" ${conf_file} || sed -i -e "/^lxc\.net\.0\.type[ \t]*=[ \t]*veth/a lxc.net.0.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" ${conf_file}
fi
if grep -q "^lxc.rootfs.path" "${conf_file}" ; then
#lxc-create already provided one
conf_rootfs_line=""
else
conf_rootfs_line="lxc.rootfs.path = $(readlink -f "${rootfs}")"
fi
if [[ "${arch}" == "x86" || "${arch}" == "amd64" ]]; then
local conf_arch_line="lxc.arch = ${arch}"
else
local conf_arch_line="# lxc.arch = ${arch}"
fi
cat <<- EOF >> "${conf_file}"
# sets container architecture
# If desired architecture != amd64 or x86, then we leave it unset as
# LXC does not oficially support anything other than x86 or amd64.
${conf_arch_line}
# set the hostname
lxc.uts.name = ${name}
lxc.tty.max = ${tty}
${conf_rootfs_line}
${portage_mount}
${conf_sysfs}
${conf_mounts}
lxc.include = ${LXC_TEMPLATE_CONFIG}/gentoo.${settings}.conf
EOF
printf " => done.\n"
}
usage()
{
cat <<EOF
$1 -h|--help [-a|--arch <arch>] [-v|--variant <variant>] [-P|--private-portage] [--portage-dir <protagedir>] [-t|--tarball <stage3file>]
[-F|--flush-cache] [-c|--cache-only] [-u|--user <username>] [-w|--password <password>] [--autologin] [-S|--auth-key <keyfile>]
[-s|--settings <name>] [-m|--mirror <gentoomirror>] [--tty <number>]
arch: the container architecture (e.g. amd64): defaults to host arch (currently: '${arch}')
If you choose one that needs emulation
tested: amd64, x86
You could try any other gentoo arch, why not...
variant: gentoo's Architecture variant as of dec 2013 : (currently: '${variant}')
for amd64 arch: amd64 (default), amd64-hardened+nomultilib, amd64-hardened, amd64-nomultilib, x32
for x86 arch: i686 (default), i486, i686-hardened
for arm arch: armv7a (default), armv7a_hardfp, armv6j, armv6j_hardfp, armv5tel, armv4tl
private-portage: by default, /usr/portage is mount-binded with host one if exists (currently: '${private_portage}')
this force container to have his own copy
portage-dir: portage dir used for shared portage
by default the host on if any (currently: '${portage_dir}')
tarball: force usage of local stage3 archive (currently: '${arch}')
If empty, latest will be downloaded
flush-cache: do like there is no previous cache
cache-only: just ensure cache is present
if cache exists and "flush-cache" not specified, does nothing
user: user used in auth oriented options (currently: '${user}')
password: password for user (currently: '${password}')
if default, usage of auth-key will disable password setting
autologin: enable autologin for user (currently: '${autologin}')
This unset default password setting
auth-key: SSH Public key file to inject into container for user (currently: '${auth_key}')
This unset default password setting
settings: choose common configuration (currently: '${settings}')
see ${LXC_TEMPLATE_CONFIG}/gentoo.*.conf
Available settings:
$(ls -1 ${LXC_TEMPLATE_CONFIG}/gentoo.*.conf | xargs basename -a -s .conf | sed 's/^gentoo.//')
mirror: gentoo mirror for download (currently: '${mirror}')
tty: number of tty (6 max) (currently: '${tty}')
EOF
exit 0
}
#some overridable defaults
set_default_arch
mirror="http://distfiles.gentoo.org"
user="root"
tty=1
settings="common"
options=$(getopt -o hp:n:a:FcPv:t:S:u:w:s:m: -l help,rootfs:,path:,name:,arch:,flush-cache,cache-only,private-portage,variant:,portage-dir:,tarball:,auth-key:,user:,autologin,password:,settings:,mirror:,tty: -- "$@")
eval set -- "$options"
while true
do
case "$1" in
-h|--help) usage $0 && exit 0;;
--rootfs) rootfs=$2; shift 2;;
-p|--path) path=$2; shift 2;;
-n|--name) name=$2; shift 2;;
-a|--arch) arch=$2; shift 2;;
-F|--flush-cache) flush_cache=1; shift 1;;
-c|--cache-only) cache_only=1; shift 1;;
-P|--private-portage) private_portage=1; shift 1;;
-v|--variant) variant=$2; shift 2;;
--portage-dir) portage_dir=$2; shift 2;;
-t|--tarball) tarball=$2; shift 2;;
-S|--auth-key) auth_key=$2; shift 2;;
-u|--user) user=$2; shift 2;;
-w|--password) forced_password=1; password=$2; shift 2;;
-s|--settings) settings=$2; shift 2;;
-m|--mirror) mirror=$2; shift 2;;
--container-cache) containercache=$2; shift 2;;
--tty) [[ $2 -lt 6 ]] && tty=$2; shift 2;;
--autologin) autologin=1; shift 1;;
--) shift 1; break ;;
*) break ;;
esac
done
# Allow the cache path to be set by environment variable
cacheroot="${LXC_CACHE_PATH:-"@LOCALSTATEDIR@/cache/lxc"}/gentoo"
portage_cache="${cacheroot}/portage.tbz"
cachefs="${cacheroot}/rootfs-${arch}-${variant}"
alias wget="wget --timeout=8 --read-timeout=15 -c -t10 -nd"
do_all() {
cache_setup
if [ -z "${cache_only}" ]; then
container_setup
fi
}
execute_exclusively "cache-${arch}-${variant}" 60 do_all

View File

@ -0,0 +1,484 @@
#!/bin/bash
#
# template script for generating openmandriva container for LXC
#
#
# lxc: linux Container library
# Authors:
# Alexander Khryukin <alexander@mezon.ru>
# Vokhmin Alexey V <avokhmin@gmail.com>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
# Detect use under userns (unsupported)
for arg in "$@"; do
[ "$arg" = "--" ] && break
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
echo "This template can't be used for unprivileged containers." 1>&2
echo "You may want to try the \"download\" template instead." 1>&2
exit 1
fi
done
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
#Configurations
#distro=cooker
hostarch=$(uname -m)
# Allow the cache base to be set by environment variable
cache_base="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/openmandriva/$arch}"
default_path=@LXCPATH@
default_profile=default
lxc_network_type=veth
lxc_network_link=br0
# is this openmandriva?
[ -f /etc/mandriva-release ] && is_openmandriva=true
configure_openmandriva()
{
mkdir -p ${rootfs_path}/etc/sysconfig/network-scripts/
# configure the network using the dhcp
cat <<EOF > ${rootfs_path}/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=dhcp
NM_CONTROLLED=no
HOSTNAME=${utsname}
EOF
# set the hostname
cat <<EOF > ${rootfs_path}/etc/sysconfig/network
NETWORKING=yes
HOSTNAME=${utsname}
EOF
echo "${utsname}" > ${rootfs_path}/etc/hostname
# set minimal hosts
cat <<EOF > $rootfs_path/etc/hosts
127.0.0.1 localhost.localdomain localhost $utsname
::1 localhost6.localdomain6 localhost6
EOF
}
populate_dev()
{
echo -n "Create devices in /dev/"
dev_path="${rootfs_path}/dev"
rm -rf $dev_path
mkdir -p $dev_path
mknod -m 666 ${dev_path}/null c 1 3
mknod -m 666 ${dev_path}/zero c 1 5
mknod -m 666 ${dev_path}/random c 1 8
mknod -m 666 ${dev_path}/urandom c 1 9
mkdir -m 755 ${dev_path}/pts
mkdir -m 1777 ${dev_path}/shm
mknod -m 666 ${dev_path}/tty c 5 0
mknod -m 666 ${dev_path}/tty0 c 4 0
mknod -m 666 ${dev_path}/tty1 c 4 1
mknod -m 666 ${dev_path}/tty2 c 4 2
mknod -m 666 ${dev_path}/tty3 c 4 3
mknod -m 666 ${dev_path}/tty4 c 4 4
mknod -m 600 ${dev_path}/console c 5 1
mknod -m 666 ${dev_path}/full c 1 7
mknod -m 600 ${dev_path}/initctl p
mknod -m 666 ${dev_path}/ptmx c 5 2
mkdir -m 755 ${dev_path}/net
mknod -m 666 ${dev_path}/net/tun c 10 200
}
set_guest_root_password()
{
[ -z "$root_password" ] && return # pass is empty, abort
echo " - setting guest root password.."
echo "root passwd is: $root_password"
echo "root:$root_password" | chroot "$rootfs_path" chpasswd
echo "done."
}
create_chroot_openmandriva()
{
# check the mini openmandriva was not already downloaded
INSTALL_ROOT=$cache/cache
mkdir -p $INSTALL_ROOT
if [ $? -ne 0 ]; then
echo "Failed to create '$INSTALL_ROOT' directory"
return 1
fi
# package list to install
PKG_LIST="basesystem-minimal locales locales-en initscripts urpmi cronie dhcp-client kbd"
# download a mini openmandriva into a cache
echo "Downloading openmandriva minimal ..."
URPMI="/usr/sbin/urpmi.addmedia --urpmi-root $INSTALL_ROOT main http://abf.rosalinux.ru/downloads/$release/repository/$arch/main/release"
echo $URPMI
URPMI_BASE="/usr/sbin/urpmi --no-suggests --no-verify-rpm --ignorearch --root $INSTALL_ROOT --urpmi-root $INSTALL_ROOT --auto $PKG_LIST"
$URPMI
$URPMI_BASE
# We're splitting the old loop into two loops plus a directory retrival.
# First loop... Try and retrive a mirror list with retries and a slight
# delay between attempts...
if [ $? -ne 0 ]; then
echo "Failed to download the rootfs, aborting."
return 1
fi
mv "$INSTALL_ROOT" "$cache/rootfs"
echo "Download complete."
return 0
}
copy_openmandriva()
{
echo -n "Copying rootfs to $rootfs_path ..."
mkdir -p $rootfs_path
rsync -SHaAX $cache/rootfs/ $rootfs_path/
return 0
}
update_openmandriva()
{
echo "automated update in progress..."
urpmi --root $cache/rootfs --urpmi-root $cache/rootfs --auto --auto-update --ignorearch
}
configure_openmandriva_systemd()
{
chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/proc-sys-fs-binfmt_misc.automount
chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd.service
chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd-control.socket
chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/systemd-udevd-kernel.socket
# remove numlock service
# KDGKBLED: Inappropriate ioctl for device
rm -f ${rootfs_path}/etc/systemd/system/getty@.service.d/enable-numlock.conf
unlink ${rootfs_path}/etc/systemd/system/default.target
chroot ${rootfs_path} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
sed -i 's!ConditionPathExists=/dev/tty0!ConditionPathExists=|/dev/tty0\nConditionVirtualization=|lxc!' \
${rootfs_path}/lib/systemd/system/getty\@.service
}
install_openmandriva()
{
mkdir -p @LOCALSTATEDIR@/lock/subsys/
(
flock -x 9
if [ $? -ne 0 ]; then
echo "Cache repository is busy."
return 1
fi
echo "Checking cache download in $cache/rootfs ... "
if [ ! -e "$cache/rootfs" ]; then
echo $cache/rootfs
create_chroot_openmandriva
if [ $? -ne 0 ]; then
echo "Failed to download 'openmandriva basesystem-minimal'"
return 1
fi
else
echo "Cache found. Updating..."
update_openmandriva
if [ $? -ne 0 ]; then
echo "Failed to update 'openmandriva base', continuing with last known good cache"
else
echo "Update finished"
fi
fi
echo "Copy $cache/rootfs to $rootfs_path ... "
copy_openmandriva
if [ $? -ne 0 ]; then
echo "Failed to copy rootfs"
return 1
fi
return 0
) 9>@LOCALSTATEDIR@/lock/subsys/lxc-openmandriva
return $?
}
copy_configuration()
{
mkdir -p $config_path
grep -q "^lxc.rootfs.path" $config_path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs_path" >> $config_path/config
cat <<EOF >> $config_path/config
lxc.uts.name = $name
lxc.tty.max = 4
lxc.pty.max = 1024
lxc.cap.drop = sys_module mac_admin mac_override sys_time
lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
# When using LXC with apparmor, uncomment the next line to run unconfined:
#lxc.apparmor.profile = unconfined
#networking
lxc.net.0.type = $lxc_network_type
lxc.net.0.flags = up
lxc.net.0.link = $lxc_network_link
lxc.net.0.name = eth0
lxc.net.0.mtu = 1500
EOF
if [ ! -z ${ipv4} ]; then
cat <<EOF >> $config_path/config
lxc.net.0.ipv4.address = $ipv4
EOF
fi
if [ ! -z ${gw} ]; then
cat <<EOF >> $config_path/config
lxc.net.0.ipv4.gateway = $gw
EOF
fi
if [ ! -z ${ipv6} ]; then
cat <<EOF >> $config_path/config
lxc.net.0.ipv6.address = $ipv6
EOF
fi
if [ ! -z ${gw6} ]; then
cat <<EOF >> $config_path/config
lxc.net.0.ipv6.gateway = $gw6
EOF
fi
cat <<EOF >> $config_path/config
#cgroups
lxc.cgroup.devices.deny = a
# /dev/null and zero
lxc.cgroup.devices.allow = c 1:3 rwm
lxc.cgroup.devices.allow = c 1:5 rwm
# consoles
lxc.cgroup.devices.allow = c 5:1 rwm
lxc.cgroup.devices.allow = c 5:0 rwm
lxc.cgroup.devices.allow = c 4:0 rwm
lxc.cgroup.devices.allow = c 4:1 rwm
# /dev/{,u}random
lxc.cgroup.devices.allow = c 1:9 rwm
lxc.cgroup.devices.allow = c 1:8 rwm
lxc.cgroup.devices.allow = c 136:* rwm
lxc.cgroup.devices.allow = c 5:2 rwm
# rtc
lxc.cgroup.devices.allow = c 10:135 rwm
EOF
if [ $? -ne 0 ]; then
echo "Failed to add configuration"
return 1
fi
return 0
}
clean()
{
if [ ! -e $cache ]; then
exit 0
fi
# lock, so we won't purge while someone is creating a repository
(
flock -x 9
if [ $? != 0 ]; then
echo "Cache repository is busy."
exit 1
fi
echo -n "Purging the download cache for OpenMandriva-$release..."
rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
exit 0
) 9>@LOCALSTATEDIR@/lock/subsys/lxc-openmandriva
}
usage()
{
cat <<EOF
usage:
$1 -n|--name=<container_name>
[-p|--path=<path>] [-c|--clean] [-R|--release=<openmandriva2013.0/rosa2012.1/cooker/ release>]
[-4|--ipv4=<ipv4 address>] [-6|--ipv6=<ipv6 address>]
[-g|--gw=<gw address>] [-d|--dns=<dns address>]
[-P|--profile=<name of the profile>] [--rootfs=<path>]
[-A|--arch=<arch of the container>]
[-h|--help]
Mandatory args:
-n,--name container name, used to as an identifier for that container from now on
Optional args:
-p,--path path to where the container rootfs will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case
-c,--clean clean the cache
-R,--release openmandriva2013.0/cooker/rosa2012.1 release for the new container. if the host is OpenMandriva, then it will default to the host's release.
-4,--ipv4 specify the ipv4 address to assign to the virtualized interface, eg. 192.168.1.123/24
-6,--ipv6 specify the ipv6 address to assign to the virtualized interface, eg. 2003:db8:1:0:214:1234:fe0b:3596/64
-g,--gw specify the default gw, eg. 192.168.1.1
-G,--gw6 specify the default gw, eg. 2003:db8:1:0:214:1234:fe0b:3596
-d,--dns specify the DNS server, eg. 192.168.1.2
-P,--profile Profile name is the file name in /etc/lxc/profiles contained packages name for install to cache.
-A,--arch Define what arch the container will be [i586,x86_64,armv7l,armv7hl]
---rootfs rootfs path
-h,--help print this help
EOF
return 0
}
options=$(getopt -o hp:n:P:cR:4:6:g:d:A -l help,rootfs:,path:,name:,profile:,clean:,release:,ipv4:,ipv6:,gw:,dns:,arch: -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
fi
eval set -- "$options"
release=${release:-"cooker"}
if [ -f /etc/lsb-release ]; then
. /etc/lsb-release
if [ "$DISTRIB_ID" = "OpenMandrivaLinux" ]; then
release=openmandriva2013.0
elif [ "$DISTRIB_ID" = "RosaDesktop.Fresh" ]; then
release=rosa2012.1
else
echo "This is not an OpenMandriva or ROSA release"
exit 1
fi
fi
while true
do
case "$1" in
-h|--help) usage $0 && exit 0;;
-p|--path) path=$2; shift 2;;
--rootfs) rootfs_path=$2; shift 2;;
-n|--name) name=$2; shift 2;;
-P|--profile) profile=$2; shift 2;;
-c|--clean) clean=1; shift 1;;
-R|--release) release=$2; shift 2;;
-A|--arch) arch=$2; shift 2;;
-4|--ipv4) ipv4=$2; shift 2;;
-6|--ipv6) ipv6=$2; shift 2;;
-g|--gw) gw=$2; shift 2;;
-d|--dns) dns=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
arch=${arch:-$hostarch}
if [ ! -z "$clean" -a -z "$path" ]; then
clean || exit 1
exit 0
fi
if [ -z "${utsname}" ]; then
utsname=${name}
fi
type urpmi >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "'urpmi' command is missing"
exit 1
fi
if [ -z "$path" ]; then
path=$default_path
fi
if [ -z "$profile" ]; then
profile=$default_profile
fi
if [ $hostarch = "i586" -a $arch = "x86_64" ]; then
echo "can't create x86_64 container on i586"
exit 1
fi
if [ -z "$ipv4" -a -z "$ipv6" ]; then
BOOTPROTO="dhcp"
else
BOOTPROTO="static"
fi
if [ "$(id -u)" != "0" ]; then
echo "This script should be run as 'root'"
exit 1
fi
# check for 'lxc.rootfs.path' passed in through default config by lxc-create
if [ -z "$rootfs_path" ]; then
if grep -q '^lxc.rootfs.path' $path/config 2>/dev/null ; then
rootfs_path=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config)
else
rootfs_path=$path/$name/rootfs
fi
fi
config_path=$default_path/$name
cache=$cache_base/$release/$arch/$profile
if [ ! -f $config_path/config ]; then
echo "A container with that name exists, chose a different name"
exit 1
fi
install_openmandriva
if [ $? -ne 0 ]; then
echo "failed to install openmandriva"
exit 1
fi
configure_openmandriva
if [ $? -ne 0 ]; then
echo "failed to configure openmandriva for a container"
exit 1
fi
# If the systemd configuration directory exists - set it up for what we need.
if [ -d ${rootfs_path}/etc/systemd/system ]
then
configure_openmandriva_systemd
fi
populate_dev
if [ $? -ne 0 ]; then
echo "failed to populated /dev/ devices"
exit 1
fi
set_guest_root_password
if [ $? -ne 0 ]; then
echo "failed to configure password for chroot"
exit 1
fi
copy_configuration
if [ $? -ne 0 ]; then
echo "failed write configuration file"
exit 1
fi
if [ ! -z "$clean" ]; then
clean || exit 1
exit 0
fi
echo "container rootfs and config created"

557
templates/lxc-opensuse.in Normal file
View File

@ -0,0 +1,557 @@
#!/bin/bash
#
# template script for generating OpenSUSE container for LXC
#
#
# lxc: linux Container library
# Authors:
# Daniel Lezcano <daniel.lezcano@free.fr>
# Frederic Crozat <fcrozat@suse.com>
# Michael H. Warfield <mhw@WittsEnd.com>
# Johannes Kastl <mail@ojkastl.de>
# Thomas Lamprecht <t.lamprecht@proxmox.com>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# Detect use under userns (unsupported)
for arg in "$@"; do
[ "$arg" = "--" ] && break
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
echo "This template can't be used for unprivileged containers." 1>&2
echo "You may want to try the \"download\" template instead." 1>&2
exit 1
fi
done
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
if [ -x /usr/bin/obs-build ]; then
BUILD=/usr/bin/obs-build
export BUILD_DIR=/usr/lib/obs-build
else
BUILD=/usr/bin/build
export BUILD_DIR=/usr/lib/build
fi
configure_opensuse()
{
rootfs=$1
hostname=$2
# set first network adapter as dhcp. This is the most common config.
cat <<EOF > $rootfs/etc/sysconfig/network/ifcfg-eth0
STARTMODE='auto'
BOOTPROTO='dhcp'
EOF
# create empty fstab
touch $rootfs/etc/fstab
# set the hostname
cat <<EOF > $rootfs/etc/HOSTNAME
$hostname
EOF
# ensure /etc/hostname is available too
ln -s -f HOSTNAME $rootfs/etc/hostname
# do not use hostname from HOSTNAME variable
cat <<EOF >> $rootfs/etc/sysconfig/cron
unset HOSTNAME
EOF
# set minimal hosts
cat <<EOF > $rootfs/etc/hosts
127.0.0.1 localhost $hostname
EOF
# disable yast->bootloader in container
cat <<EOF > $rootfs/etc/sysconfig/bootloader
LOADER_TYPE=none
LOADER_LOCATION=none
EOF
# set /dev/console as securetty
cat << EOF >> $rootfs/etc/securetty
console
EOF
cat <<EOF >> $rootfs/etc/sysconfig/boot
# disable root fsck
ROOTFS_FSCK="0"
ROOTFS_BLKDEV="/dev/null"
EOF
# remove pointless services in a container
ln -s /dev/null $rootfs/etc/systemd/system/proc-sys-fs-binfmt_misc.automount
ln -s /dev/null $rootfs/etc/systemd/system/console-shell.service
ln -s /dev/null $rootfs/etc/systemd/system/systemd-vconsole-setup.service
# enable getty and console services
sed -e 's/ConditionPathExists=.*//' $rootfs/usr/lib/systemd/system/getty@.service > $rootfs/etc/systemd/system/getty@.service
ln -s getty@.service $rootfs/etc/systemd/system/getty@tty1.service
mkdir -p $rootfs/etc/systemd/system/getty.target.wants/
ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@console.service
ln -s -f ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty1.service
ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty2.service
ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty3.service
ln -s ../getty@.service $rootfs/etc/systemd/system/getty.target.wants/getty@tty4.service
touch $rootfs/etc/sysconfig/kernel
echo "Please change root-password !"
return 0
}
download_opensuse()
{
cache=$1
arch=$2
if [ ! -x ${BUILD} ]; then
echo "Could not create openSUSE template :"
echo "you need to install \"build\" package"
return 1
fi
# check the mini opensuse was not already downloaded
mkdir -p "$cache/partial-$arch"
if [ $? -ne 0 ]; then
echo "Failed to create '$cache/partial-$arch' directory"
return 1
fi
# download a mini opensuse into a cache
echo "Downloading opensuse minimal ..."
mkdir -p "$cache/partial-$arch-packages"
oss_repo_url="http://download.opensuse.org/distribution/$DISTRO/repo/oss/"
if [[ $DISTRO == "tumbleweed" ]]; then
oss_repo_url="http://download.opensuse.org/$DISTRO/repo/oss/"
fi
zypper --quiet --root $cache/partial-$arch-packages --non-interactive ar "$oss_repo_url" repo-oss || return 1
update_repo_url="http://download.opensuse.org/update/$DISTRO/repo/oss"
# Leap update repos were rearranged
if [[ $DISTRO == "leap/4"* ]]; then
update_repo_url="http://download.opensuse.org/update/$DISTRO/oss/"
fi
# tumbleweed has no update repo
if [[ $DISTRO != "tumbleweed" ]]; then
zypper --quiet --root $cache/partial-$arch-packages --non-interactive ar "$update_repo_url" update || return 1
fi
zypper --quiet --root $cache/partial-$arch-packages --non-interactive --gpg-auto-import-keys update || return 1
zypper --root $cache/partial-$arch-packages --non-interactive in --auto-agree-with-licenses --download-only zypper lxc patterns-openSUSE-base bash iputils sed tar rsyslog || return 1
cat > $cache/partial-$arch-packages/opensuse.conf << EOF
Preinstall: aaa_base bash coreutils diffutils
Preinstall: filesystem fillup glibc grep insserv-compat perl-base
Preinstall: libbz2-1 pam
Preinstall: permissions rpm sed tar libz1 libselinux1
Preinstall: liblzma5 libcap2 libacl1 libattr1
Preinstall: libpopt0 libelf1
Preinstall: libpcre1
RunScripts: aaa_base
Support: zypper
Support: patterns-openSUSE-base
Support: lxc
Support: ncurses-utils
Support: iputils
Support: udev
Support: netcfg
Support: hwinfo insserv-compat module-init-tools openSUSE-release openssh
Support: pwdutils sysconfig
Ignore: rpm:suse-build-key,build-key
Ignore: systemd:systemd-presets-branding
EOF
if [ $DISTRO = "13.2" ]
then
echo "Support: python3-base" >> $cache/partial-$arch-packages/opensuse.conf
fi
if [[ $DISTRO == "tumbleweed" ]]; then
echo "Preinstall: liblua5_3 libncurses6 libreadline7" >> $cache/partial-$arch-packages/opensuse.conf
else
echo "Preinstall: liblua5_1 libncurses5 libreadline6" >> $cache/partial-$arch-packages/opensuse.conf
echo "Support: rpcbind" >> $cache/partial-$arch-packages/opensuse.conf
fi
# dhcpcd is not in the default repos since Leap 42.1, neither in tumbleweed
if [[ $DISTRO != "leap/4"* ]] && [[ $DISTRO != "tumbleweed" ]]; then
echo "Support: dhcpcd" >> $cache/partial-$arch-packages/opensuse.conf
fi
# Leap and tumbleweed doesn't seem to have iproute2 utils installed
if [[ $DISTRO == "leap/4"* ]] || [[ $DISTRO == "tumbleweed" ]]; then
echo "Support: net-tools iproute2" >> $cache/partial-$arch-packages/opensuse.conf
fi
if [ "$arch" = "i686" ]; then
mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i686/
for i in "$cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i586/*" ; do
ln -s $i $cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/i686/
done
mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/update/i686
for i in "$cache/partial-$arch-packages/var/cache/zypp/packages/update/i586/*" ; do
ln -s $i $cache/partial-$arch-packages/var/cache/zypp/packages/update/i686/
done
fi
# openSUSE 13.2 has no noarch directory in update
[ -d $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch ] || mkdir -p $cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch
repos=("--repository" "$cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/$arch" "--repository" "$cache/partial-$arch-packages/var/cache/zypp/packages/repo-oss/suse/noarch")
if [[ $DISTRO != "tumbleweed" ]]; then # tumbleweed has no update repo
repos+=("--repository" "$cache/partial-$arch-packages/var/cache/zypp/packages/update/$arch" "--repository" "$cache/partial-$arch-packages/var/cache/zypp/packages/update/noarch")
fi
CLEAN_BUILD=1 BUILD_ARCH="$arch" BUILD_ROOT="$cache/partial-$arch" BUILD_DIST="$cache/partial-$arch-packages/opensuse.conf" PATH="$PATH:$BUILD_DIR" $BUILD_DIR/init_buildsystem --clean --configdir $BUILD_DIR/configs --cachedir $cache/partial-$arch-cache ${repos[*]} || return 1
chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar "$oss_repo_url" repo-oss || return 1
if [[ $DISTRO != "tumbleweed" ]]; then
chroot $cache/partial-$arch /usr/bin/zypper --quiet --non-interactive ar "$update_repo_url" update || return 1
fi
# really clean the image
rm -fr $cache/partial-$arch/{.build,.guessed_dist,.srcfiles*,installed-pkg}
rm -fr $cache/partial-$arch/dev
# make sure we have a minimal /dev
mkdir -p "$cache/partial-$arch/dev"
mknod -m 666 $cache/partial-$arch/dev/null c 1 3
mknod -m 666 $cache/partial-$arch/dev/zero c 1 5
# create mtab symlink
rm -f $cache/partial-$arch/etc/mtab
ln -sf /proc/self/mounts $cache/partial-$arch/etc/mtab
# ensure /var/run and /run are symlinked
rm -fr $cache/partial-$arch/var/run
ln -s -f ../run $cache/partial-$arch/var/run
if [ $? -ne 0 ]; then
echo "Failed to download the rootfs, aborting."
return 1
fi
rm -fr "$cache/partial-$arch-packages"
mv "$1/partial-$arch" "$1/rootfs-$arch"
echo "Download complete."
return 0
}
copy_opensuse()
{
cache=$1
arch=$2
rootfs=$3
# make a local copy of the mini opensuse
echo "Copying rootfs to $rootfs ..."
mkdir -p $rootfs
rsync -SHaAX $cache/rootfs-$arch/ $rootfs/ || return 1
return 0
}
install_opensuse()
{
# Allow the cache base to be set by environment variable
cache="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/opensuse/$DISTRO}"
rootfs=$1
mkdir -p @LOCALSTATEDIR@/lock/subsys/
(
flock -x 9
if [ $? -ne 0 ]; then
echo "Cache repository is busy."
return 1
fi
echo "Checking cache download in $cache/rootfs-$arch ... "
if [ ! -e "$cache/rootfs-$arch" ]; then
download_opensuse $cache $arch
if [ $? -ne 0 ]; then
echo "Failed to download 'opensuse base'"
return 1
fi
fi
echo "Copy $cache/rootfs-$arch to $rootfs ... "
copy_opensuse $cache $arch $rootfs
if [ $? -ne 0 ]; then
echo "Failed to copy rootfs"
return 1
fi
return 0
) 9>@LOCALSTATEDIR@/lock/subsys/lxc-opensuse
return $?
}
# Generate a random hardware (MAC) address composed of FE followed by
# 5 random bytes...
create_hwaddr()
{
openssl rand -hex 5 | sed -e 's/\(..\)/:\1/g; s/^/fe/'
}
copy_configuration()
{
path=$1
rootfs=$2
name=$3
grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo "
lxc.rootfs.path = $rootfs_path
" >> $path/config
# The following code is to create static MAC addresses for each
# interface in the container. This code will work for multiple
# interfaces in the default config. It will also strip any
# hwaddr stanzas out of the default config since we can not share
# MAC addresses between containers.
#
# This code is largely mimiced from the Fedora Template.
mv $path/config $path/config.def
while read LINE
do
# This should catch variable expansions from the default config...
if expr "${LINE}" : '.*\$' > /dev/null 2>&1
then
LINE=$(eval "echo \"${LINE}\"")
fi
# There is a tab and a space in the regex bracket below!
# Seems that \s doesn't work in brackets.
KEY=$(expr "${LINE}" : '\s*\([^ ]*\)\s*=')
if [[ "${KEY}" != "lxc.net.0.hwaddr" ]]
then
echo "${LINE}" >> $path/config
if [[ "${KEY}" == "lxc.net.0.link" ]]
then
echo "lxc.net.0.hwaddr = $(create_hwaddr)" >> $path/config
fi
fi
done < $path/config.def
rm -f $path/config.def
if [ -e "@LXCTEMPLATECONFIG@/opensuse.common.conf" ]; then
echo "
# Include common configuration
lxc.include = @LXCTEMPLATECONFIG@/opensuse.common.conf
" >> $path/config
fi
# Append things which require expansion here...
cat <<EOF >> $path/config
lxc.arch = $arch
lxc.uts.name = $name
lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
# When using LXC with apparmor, uncomment the next line to run unconfined:
lxc.apparmor.profile = unconfined
# example simple networking setup, uncomment to enable
#lxc.net.0.type = $lxc_network_type
#lxc.net.0.flags = up
#lxc.net.0.link = $lxc_network_link
#lxc.net.0.name = eth0
# Additional example for veth network type
# static MAC address,
#lxc.net.0.hwaddr = 00:16:3e:77:52:20
# persistent veth device name on host side
# Note: This may potentially collide with other containers of same name!
#lxc.net.0.veth.pair = v-$name-e0
EOF
if [ $? -ne 0 ]; then
echo "Failed to add configuration"
return 1
fi
return 0
}
clean()
{
cache="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc/opensuse}"
if [ ! -e $cache ]; then
exit 0
fi
# lock, so we won't purge while someone is creating a repository
(
flock -x 9
if [ $? != 0 ]; then
echo "Cache repository is busy."
exit 1
fi
echo -n "Purging the download cache..."
rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
exit 0
) 9>@LOCALSTATEDIR@/lock/subsys/lxc-opensuse
}
usage()
{
cat <<EOF
$1 -h|--help -p|--path=<path> -r|--release nn.n --clean
Please give the release as 13.1, 13.2 etc.
If no release is given, openSUSE Leap 42.2 is installed.
EOF
return 0
}
# Make arch a global. This may become configurable?
arch=$(uname -m)
options=$(getopt -o hp:n:r:c -l help,rootfs:,path:,name:,release:,clean -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
fi
eval set -- "$options"
while true
do
case "$1" in
-h|--help) usage $0 && exit 0;;
-p|--path) path=$2; shift 2;;
--rootfs) rootfs=$2; shift 2;;
-n|--name) name=$2; shift 2;;
-r|--release) DISTRO=$2; shift 2;;
-c|--clean) clean=1; shift 1;;
--) shift 1; break ;;
*) break ;;
esac
done
if [ ! -z "$clean" -a -z "$path" ]; then
clean || exit 1
exit 0
fi
type zypper > /dev/null
if [ $? -ne 0 ]; then
echo "'zypper' command is missing"
exit 1
fi
if [ -z "$path" ]; then
echo "'path' parameter is required"
exit 1
fi
if grep -q Harlequin /etc/os-release || grep -q Tumbleweed /etc/os-release ; then
BVER=`rpm -q --qf '%{version}\n' build`
if [ $? -ne 0 -o "$BVER" -lt "20141120" ]; then
echo "Building openSUSE containers with your version of the build package is broken. Please install the update to version 20141120 or newer."
exit 1
fi
fi
if [ -z "$DISTRO" ]; then
echo ""
echo "No release selected, using openSUSE Leap 42.2"
DISTRO="leap/42.2"
else
echo ""
case "$DISTRO" in
13.1)
echo "Selected openSUSE 13.1"
;;
13.2)
echo "Selected openSUSE 13.2"
;;
42.1|leap/42.1|leap)
echo "Selected openSUSE Leap 42.1"
DISTRO="leap/42.1"
;;
42.2|leap/42.2|422)
echo "Selected openSUSE Leap 42.2"
DISTRO="leap/42.2"
;;
42.3|leap/42.3|423)
echo "Selected openSUSE Leap 42.3"
DISTRO="leap/42.3"
;;
tumbleweed|factory)
echo "Selected openSUSE Leap Tumbleweed"
DISTRO="tumbleweed"
;;
*)
echo "You have chosen an invalid release, quitting..."
exit 1
;;
esac
fi
if [ "$(id -u)" != "0" ]; then
echo "This script should be run as 'root'"
exit 1
fi
# detect rootfs
config="$path/config"
if [ -z "$rootfs" ]; then
if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then
rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config)
else
rootfs=$path/rootfs
fi
fi
install_opensuse $rootfs
if [ $? -ne 0 ]; then
echo "failed to install opensuse"
exit 1
fi
configure_opensuse $rootfs $name
if [ $? -ne 0 ]; then
echo "failed to configure opensuse for a container"
exit 1
fi
copy_configuration $path $rootfs $name
if [ $? -ne 0 ]; then
echo "failed write configuration file"
exit 1
fi
if [ ! -z "$clean" ]; then
clean || exit 1
exit 0
fi

972
templates/lxc-oracle.in Normal file
View File

@ -0,0 +1,972 @@
#!/bin/sh
#
# Template script for generating Oracle Enterprise Linux container for LXC
# based on lxc-fedora, lxc-ubuntu
#
# Copyright © 2011 Wim Coekaerts <wim.coekaerts@oracle.com>
# Copyright © 2012 Dwight Engen <dwight.engen@oracle.com>
#
# Modified for Oracle Linux 5
# Wim Coekaerts <wim.coekaerts@oracle.com>
#
# Modified for Oracle Linux 6,7 combined OL4,5,6 into one template script
# Dwight Engen <dwight.engen@oracle.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
# Detect use under userns (unsupported)
for arg in "$@"; do
[ "$arg" = "--" ] && break
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
echo "This template can't be used for unprivileged containers." 1>&2
echo "You may want to try the \"download\" template instead." 1>&2
exit 1
fi
done
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
die()
{
echo "failed: $1"
exit 1
}
is_btrfs_subvolume()
{
if which btrfs >/dev/null 2>&1 && \
btrfs subvolume list "$1" >/dev/null 2>&1; then
return 0
fi
return 1
}
can_chcon()
{
if which chcon >/dev/null 2>&1; then
selinuxenabled >/dev/null 2>&1
return $?
fi
return 1
}
# fix up the container_rootfs
container_rootfs_patch()
{
echo "Patching container rootfs $container_rootfs for Oracle Linux $container_release_major.$container_release_minor"
# copy ourself into the container to be used to --patch the rootfs when
# yum update on certain packages is done. we do this here instead of in
# container_rootfs_configure() in case the patching done in this function
# is updated in the future, we can inject the updated version of ourself
# into older containers.
if [ $container_rootfs != "/" ]; then
cp -f `readlink -f $0` $container_rootfs/usr/bin/lxc-patch
if [ $container_release_major -lt "6" ]; then
mkdir -p $container_rootfs/usr/lib/yum-plugins
cp @DATADIR@/lxc/lxc-patch.py $container_rootfs/usr/lib/yum-plugins
fi
if [ $container_release_major -ge "6" ]; then
mkdir -p $container_rootfs/usr/share/yum-plugins
cp @DATADIR@/lxc/lxc-patch.py $container_rootfs/usr/share/yum-plugins
fi
mkdir -p $container_rootfs/etc/yum/pluginconf.d
cat <<EOF > $container_rootfs/etc/yum/pluginconf.d/lxc-patch.conf
[main]
enabled=1
packages=dbus,initscripts,iptables,openssh-server,setup,selinux-policy,readahead,udev,util-linux,util-linux-ng
EOF
fi
if [ $container_release_major = "4" ]; then
# yum plugin type of TYPE_INTERFACE works in all releases but gives a
# deprecation warning on major > 4, so we default to TYPE_INTERACTIVE
# and fix it up here
sed -i 's|TYPE_INTERACTIVE|TYPE_INTERFACE|' $container_rootfs/usr/lib/yum-plugins/lxc-patch.py
if [ -f $container_rootfs/etc/yum.repos.d/ULN-Base.repo ]; then
mv $container_rootfs/etc/yum.repos.d/ULN-Base.repo \
$container_rootfs/etc/yum.repos.d/ULN-Base.repo.lxc-disabled
fi
echo "plugins = 1" >>$container_rootfs/etc/yum.conf
fi
# "disable" selinux in the guest. The policy in the container isn't
# likely to match the hosts (unless host == guest exactly) and the
# kernel can only be enforcing one policy.
#
# The OL 5 init honors /etc/selinux/config, but note that
# this doesnt actually disable it if it's enabled in the host, since
# libselinux::is_selinux_enabled() in the guest will check
# /proc/filesystems and see selinuxfs, thus reporting that it is on
# (ie. check the output of sestatus in the guest). We also replace
# /usr/sbin/selinuxenabled with a symlink to /bin/false so that init
# scripts (ie. mcstransd) that call that think selinux is disabled.
mkdir -p $container_rootfs/selinux
echo 0 > $container_rootfs/selinux/enforce
if [ -e $container_rootfs/etc/selinux/config ]; then
sed -i 's|SELINUX=enforcing|SELINUX=disabled|' $container_rootfs/etc/selinux/config
else
mkdir -p $container_rootfs/etc/selinux
echo "SELINUX=disabled" >$container_rootfs/etc/selinux/config
fi
sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*close|#session required pam_selinux.so close|' $container_rootfs/etc/pam.d/login
sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*open|#session required pam_selinux.so open|' $container_rootfs/etc/pam.d/login
sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*close|#session required pam_selinux.so close|' $container_rootfs/etc/pam.d/sshd
sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*open|#session required pam_selinux.so open|' $container_rootfs/etc/pam.d/sshd
# setting /proc/$$/loginuid doesn't work under user namespace, which
# prevents logins from working
sed -i 's|session[ \t]*required[ \t]*pam_loginuid.so|#session required pam_loginuid.so|' $container_rootfs/etc/pam.d/sshd
sed -i 's|session[ \t]*required[ \t]*pam_loginuid.so|#session required pam_loginuid.so|' $container_rootfs/etc/pam.d/login
if [ -f $container_rootfs/usr/sbin/selinuxenabled ]; then
mv $container_rootfs/usr/sbin/selinuxenabled $container_rootfs/usr/sbin/selinuxenabled.lxcorig
ln -s /bin/false $container_rootfs/usr/sbin/selinuxenabled
fi
# ensure /dev/ptmx refers to the newinstance devpts of the container, or
# pty's will get crossed up with the hosts (https://lkml.org/lkml/2012/1/23/512)
rm -f $container_rootfs/dev/ptmx
ln -s pts/ptmx $container_rootfs/dev/ptmx
# OL7 has systemd, no rc.sysinit
if [ $container_release_major = "7" ]; then
# with newer systemd (OL7.2), getty service include container-getty.service
# let that be the one who manage the getty service instead
if [ ! -f $container_rootfs/usr/lib/systemd/system/container-getty@.service ]; then
# from mhw in the fedora template: We do need to disable the
# "ConditionalPathExists=/dev/tty0" line or no gettys are started on
# the ttys in the container. Lets do it in an override copy of the
# service so it can still pass rpm verifies and not be automatically
# updated by a new systemd version.
sed -e 's/^ConditionPathExists=/#LXC ConditionPathExists=/' \
< $container_rootfs/usr/lib/systemd/system/getty\@.service \
> $container_rootfs/etc/systemd/system/getty\@.service
# Setup getty service on the 4 ttys we are going to allow in the
# default config. Number should match lxc.tty
( cd $container_rootfs/etc/systemd/system/getty.target.wants
for i in 1 2 3 4 ; do ln -sf ../getty\@.service getty@tty${i}.service; done )
# We only want to spawn a getty on /dev/console in lxc, libvirt-lxc
# symlinks /dev/console to /dev/tty1
sed -i '/Before=getty.target/a ConditionVirtualization=lxc' $container_rootfs/usr/lib/systemd/system/console-getty.service
fi
# disable some systemd services, set default boot, sigpwr target
rm -f $container_rootfs/usr/lib/systemd/system/sysinit.target.wants/kmod-static-nodes.service
chroot $container_rootfs systemctl -q disable graphical.target
chroot $container_rootfs systemctl -q enable multi-user.target
# systemd in userns won't be able to set /proc/self/oom_score_adj which
# prevents the dbus service from starting
sed -i 's|^OOMScoreAdjust|#LXC OOMScoreAdjust|' $container_rootfs/usr/lib/systemd/system/dbus.service
return
fi
# silence error in checking for selinux
sed -i 's|cat /proc/self/attr/current|cat /proc/self/attr/current 2>/dev/null|' $container_rootfs/etc/rc.sysinit
sed -i 's|cat /proc/self/attr/current|cat /proc/self/attr/current 2>/dev/null|' $container_rootfs/etc/rc.d/rc.sysinit
# on ol4 pam_limits prevents logins when using user namespaces
if [ $container_release_major = "4" ]; then
sed -i 's|session[ \t]*required[ \t]*/lib/security/\$ISA/pam_limits.so|#session required /lib/security/$ISA/pam_limits.so|' $container_rootfs/etc/pam.d/system-auth
fi
# avoid error in ol5 attempting to copy non-existent resolv.conf
if [ $container_release_major = "5" ]; then
sed -i 's|resolv.conf.predhclient|resolv.conf.predhclient 2>/dev/null|' $container_rootfs/sbin/dhclient-script
fi
# disable interactive ovmd asking questions
if [ -f $container_rootfs/etc/sysconfig/ovmd ]; then
sed -i 's|INITIAL_CONFIG=yes|INITIAL_CONFIG=no|' $container_rootfs/etc/sysconfig/ovmd
fi
# disable disabling of ipv4 forwarding and defrag on shutdown since
# we mount /proc/sys ro
if [ $container_release_major = "5" ]; then
sed -i 's|-f /proc/sys/net/ipv4/ip_forward|-w /proc/sys/net/ipv4/ip_forward|' $container_rootfs/etc/rc.d/init.d/network
sed -i 's|-f /proc/sys/net/ipv4/ip_always_defrag|-w /proc/sys/net/ipv4/ip_always_defrag|' $container_rootfs/etc/rc.d/init.d/network
fi
# disable ipv6 on ol6
rm -f $container_rootfs/etc/sysconfig/network-scripts/init.ipv6-global
# remove module stuff for iptables it just shows errors that are not
# relevant in a container
if [ -f "$container_rootfs/etc/sysconfig/iptables-config" ]; then
sed -i 's|IPTABLES_MODULES=".*|IPTABLES_MODULES=""|' $container_rootfs/etc/sysconfig/iptables-config
sed -i 's|IPTABLES_MODULES_UNLOAD=".*|IPTABLES_MODULES_UNLOAD="no"|' $container_rootfs/etc/sysconfig/iptables-config
fi
# disable readahead in the container
if [ $container_release_major = "6" -a -e $container_rootfs/etc/sysconfig/readahead ]; then
rm -f $container_rootfs/etc/init/readahead-collector.conf
rm -f $container_rootfs/etc/init/readahead-disable-services.conf
sed -i 's|READAHEAD="yes"|READAHEAD="no"|' $container_rootfs/etc/sysconfig/readahead
fi
if [ $container_release_major = "4" ]; then
# enable fastboot always
sed -i 's|\[ -f /fastboot \]|/bin/true|' $container_rootfs/etc/rc.sysinit
sed -i 's|\[ -f /fastboot \]|/bin/true|' $container_rootfs/etc/rc.d/rc.sysinit
# dont attempt to set kernel parameters
sed -i 's|action $"Configuring kernel parameters|# LXC action $"Configuring kernel parameters|' $container_rootfs/etc/rc.sysinit
sed -i 's|action $"Configuring kernel parameters|# LXC action $"Configuring kernel parameters|' $container_rootfs/etc/rc.d/rc.sysinit
sed -i 's|action $"Setting network parameters|# LXC action $"Setting network parameters|' $container_rootfs/etc/init.d/network 2>/dev/null
sed -i 's|action $"Setting network parameters|# LXC action $"Setting network parameters|' $container_rootfs/etc/init.d/NetworkManager 2>/dev/null
fi
# no need to attempt to mount /
sed -i 's|mount -f /$|# LXC mount -f /|' $container_rootfs/etc/rc.sysinit
sed -i 's|mount -f /$|# LXC mount -f /|' $container_rootfs/etc/rc.d/rc.sysinit
sed -i 's|action \$"Remounting root filesystem|/bin/true # LXC action $"Remounting root filesystem|' $container_rootfs/etc/rc.sysinit
sed -i 's|action \$"Remounting root filesystem|/bin/true # LXC action $"Remounting root filesystem|' $container_rootfs/etc/rc.d/rc.sysinit
# disable udev in the container
if [ $container_release_major = "4" ]; then
sed -i 's|\[ -x /sbin/start_udev \]|# LXC no udev|' $container_rootfs/etc/rc.sysinit
sed -i 's|\[ -x /sbin/start_udev \]|# LXC no udev|' $container_rootfs/etc/rc.d/rc.sysinit
else
sed -i 's|.sbin.start_udev||' $container_rootfs/etc/rc.sysinit
sed -i 's|.sbin.start_udev||' $container_rootfs/etc/rc.d/rc.sysinit
fi
# disable nash raidautorun in the container since no /dev/md*
if [ $container_release_major = "4" -o $container_release_major = "5" ]; then
sed -i 's|echo "raidautorun /dev/md0"|echo ""|' $container_rootfs/etc/rc.sysinit
sed -i 's|echo "raidautorun /dev/md0"|echo ""|' $container_rootfs/etc/rc.d/rc.sysinit
fi
# prevent rc.sysinit from attempting to loadkeys
if [ \( $container_release_major = "4" -o $container_release_major = "5" \) -a -e $container_rootfs/etc/sysconfig/keyboard ]; then
rm $container_rootfs/etc/sysconfig/keyboard
fi
# dont use the hwclock, it messes up the host's time
if [ $container_release_major = "4" ]; then
sed -i 's|runcmd $"Syncing hardware clock|# LXC no hwclock runcmd $"Syncing hardware clock|' $container_rootfs/etc/rc.d/init.d/halt
else
sed -i 's|\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.d/init.d/halt
fi
sed -i 's|^\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.sysinit
sed -i 's|^\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.d/rc.sysinit
sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.sysinit
sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.d/rc.sysinit
# dont start lvm
if [ $container_release_major -lt "6" -a -f $container_rootfs/sbin/lvm.static ]; then
mv $container_rootfs/sbin/lvm.static $container_rootfs/sbin/lvm.static.lxc-disabled
fi
if [ $container_release_major = "6" ]; then
touch $container_rootfs/.nolvm
fi
# fix assumptions that plymouth is available
sed -i 's|\[ "$PROMPT" != no \] && plymouth|[ "$PROMPT" != no ] \&\& [ -n "$PLYMOUTH" ] \&\& plymouth|' $container_rootfs/etc/rc.sysinit
sed -i 's|\[ "$PROMPT" != no \] && plymouth|[ "$PROMPT" != no ] \&\& [ -n "$PLYMOUTH" ] \&\& plymouth|' $container_rootfs/etc/rc.d/rc.sysinit
rm -f $container_rootfs/etc/init/plymouth-shutdown.conf
rm -f $container_rootfs/etc/init/quit-plymouth.conf
rm -f $container_rootfs/etc/init/splash-manager.conf
# dont try to unmount /dev/lxc devices
sed -i 's|&& $1 !~ /^\\/dev\\/ram/|\&\& $2 !~ /^\\/dev\\/lxc/ \&\& $1 !~ /^\\/dev\\/ram/|' $container_rootfs/etc/init.d/halt
# don't try to unmount swap
sed -i 's|\[ -f /proc/swaps \]|# LXC [ -f /proc/swaps ]|' $container_rootfs/etc/init.d/halt
# sem_open(3) checks that /dev/shm is SHMFS_SUPER_MAGIC, so make sure to
# mount /dev/shm (normally done by dracut initrd) as tmpfs
if [ $container_release_major = "4" -o $container_release_major = "5" ]; then
grep -q "mount -t tmpfs tmpfs /dev/shm" $container_rootfs/etc/rc.sysinit
if [ $? -eq 1 ]; then
echo "mkdir -p /dev/shm && mount -t tmpfs tmpfs /dev/shm" >>$container_rootfs/etc/rc.sysinit
echo "mkdir -p /dev/shm && mount -t tmpfs tmpfs /dev/shm" >>$container_rootfs/etc/rc.d/rc.sysinit
fi
fi
if [ $container_release_major = "6" ]; then
sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.sysinit
sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.d/rc.sysinit
fi
# there might be other services that are useless but the below set is a good start
# some of these might not exist in the image, so we silence chkconfig complaining
# about the service file not being found
for service in \
acpid apmd auditd autofs cpuspeed dund gpm haldaemon hidd \
ip6tables irqbalance iscsi iscsid isdn kdump kudzu \
lm_sensors lvm2-monitor mdmonitor microcode_ctl \
ntpd pcmcia postfix sendmail udev-post xfs ;
do
chroot $container_rootfs chkconfig 2>/dev/null $service off
done
for service in rsyslog ;
do
chroot $container_rootfs chkconfig 2>/dev/null $service on
done
}
container_rootfs_configure()
{
container_rootfs_patch
echo "Configuring container for Oracle Linux $container_release_major.$container_release_minor"
# configure the network to use dhcp. we set DHCP_HOSTNAME so the guest
# will report its name and be resolv'able by the hosts dnsmasq
cat <<EOF > $container_rootfs/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
HOSTNAME=$name
DHCP_HOSTNAME=\`hostname\`
NM_CONTROLLED=no
TYPE=Ethernet
EOF
# set the hostname
if [ $container_release_major -ge "7" ]; then
# systemd honors /etc/hostname
echo "$name" >$container_rootfs/etc/hostname
fi
cat <<EOF > $container_rootfs/etc/sysconfig/network
NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=$name
EOF
# set minimal hosts
echo "127.0.0.1 localhost $name" > $container_rootfs/etc/hosts
# this file has to exist for libvirt/Virtual machine monitor to boot the container
touch $container_rootfs/etc/mtab
# setup console and tty[1-4] for login. note that /dev/console and
# /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and
# /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks.
# lxc will maintain these links and bind mount ptys over /dev/lxc/*
# since lxc.tty.dir is specified in the config.
# allow root login on console, tty[1-4], and pts/0 for libvirt
echo "# LXC (Linux Containers)" >>$container_rootfs/etc/securetty
echo "lxc/console" >>$container_rootfs/etc/securetty
for i in 1 2 3 4; do
echo "lxc/tty$i" >>$container_rootfs/etc/securetty
done
echo "# For libvirt/Virtual Machine Monitor" >>$container_rootfs/etc/securetty
for i in 0 1 2 3 4; do
echo "pts/$i" >>$container_rootfs/etc/securetty
done
# prevent mingetty from calling vhangup(2) since it fails with userns
if [ -f $container_rootfs/etc/init/tty.conf ]; then
sed -i 's|mingetty|mingetty --nohangup|' $container_rootfs/etc/init/tty.conf
fi
# create maygetty which only spawns a getty on the console when running
# under lxc, not libvirt-lxc which symlinks /dev/console to the same pty
# as /dev/tty1
cat <<EOF >$container_rootfs/sbin/maygetty
#!/bin/sh
if [ "\$container" = "lxc" ]; then
exec /sbin/mingetty \$@
fi
exec sleep infinity
EOF
chmod 755 $container_rootfs/sbin/maygetty
# start a getty on /dev/console, /dev/tty[1-4]
if [ $container_release_major = "4" -o $container_release_major = "5" ]; then
sed -i 's|mingetty|mingetty --nohangup|' $container_rootfs/etc/inittab
sed -i '/1:2345:respawn/i cns:2345:respawn:/sbin/maygetty --nohangup --noclear console' $container_rootfs/etc/inittab
sed -i '/5:2345:respawn/d' $container_rootfs/etc/inittab
sed -i '/6:2345:respawn/d' $container_rootfs/etc/inittab
fi
if [ $container_release_major = "6" ]; then
cat <<EOF > $container_rootfs/etc/init/console.conf
# console - getty
#
# This service maintains a getty on the console from the point the system is
# started until it is shut down again.
start on stopped rc RUNLEVEL=[2345]
stop on runlevel [!2345]
env container
respawn
exec /sbin/maygetty --nohangup --noclear /dev/console
EOF
fi
# lxc-shutdown sends SIGPWR to init, OL4 and OL5 have SysVInit, just
# make it do shutdown now instead of delaying 2 minutes. OL6 uses
# upstart, so we create an upstart job to handle SIGPWR to shut down
# cleanly. We use "init 0" instead of shutdown -h now to avoid SELinux
# permission denied when upstart's shutdown tries to connect to the
# /com/ubuntu/upstart socket.
if [ $container_release_major = "4" -o $container_release_major = "5" ]; then
sed -i 's|pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; |pf::powerfail:/sbin/shutdown -f -h now "|' $container_rootfs/etc/inittab
elif [ $container_release_major = "6" ]; then
cat <<EOF > $container_rootfs/etc/init/power-status-changed.conf
# power-status-changed - used to cleanly shut down the container
#
# This task is run whenever init receives SIGPWR
# Used to shut down the machine.
start on power-status-changed
exec init 0
EOF
fi
# start with a clean /var/log/messages
rm -f $container_rootfs/var/log/messages
# set initial timezone as on host
if [ -f /etc/sysconfig/clock ]; then
. /etc/sysconfig/clock
if [ $container_release_major = "5" -o $container_release_major = "6" ]; then
echo ZONE=$ZONE > $container_rootfs/etc/sysconfig/clock
chroot $container_rootfs tzdata-update
else
ZONE="${ZONE// /_}"
chroot $container_rootfs ln -sf ../usr/share/zoneinfo/$ZONE /etc/localtime
fi
else
ZONE=`readlink /etc/localtime | sed -s "s/\.\.\/usr\/share\/zoneinfo\///g"`
if [ "$ZONE" ]; then
if [ $container_release_major = "5" -o $container_release_major = "6" ]; then
echo ZONE=$ZONE > $container_rootfs/etc/sysconfig/clock
chroot $container_rootfs tzdata-update
else
# if /etc/localtime is a symlink, this should preserve it.
cp -a /etc/localtime $container_rootfs/etc/localtime
fi
else
echo "Timezone in container is not configured. Adjust it manually."
fi
fi
# add oracle user
chroot $container_rootfs useradd -m -s /bin/bash oracle
printf "Added container user:\033[1moracle\033[0m\n"
printf "Added container user:\033[1mroot\033[0m\n"
}
# create the container's lxc config file
container_config_create()
{
echo "Create configuration file $cfg_dir/config"
mkdir -p $cfg_dir || die "unable to create config dir $cfg_dir"
echo "# Common configuration" >> $cfg_dir/config
if [ -e "@LXCTEMPLATECONFIG@/oracle.common.conf" ]; then
echo "lxc.include = @LXCTEMPLATECONFIG@/oracle.common.conf" >> $cfg_dir/config
fi
cat <<EOF >> $cfg_dir/config || die "unable to create $cfg_dir/config"
# Container configuration for Oracle Linux $container_release_major.$container_release_minor
lxc.arch = $arch
lxc.uts.name = $name
EOF
grep -q "^lxc.rootfs.path" $cfg_dir/config 2>/dev/null || echo "lxc.rootfs.path = $container_rootfs" >> $cfg_dir/config
if [ $container_release_major != "4" ]; then
echo "lxc.cap.drop = sys_resource" >>$cfg_dir/config
fi
# systemd services like logind and journald need these
if [ $container_release_major != "7" ]; then
echo "lxc.cap.drop = setfcap setpcap" >>$cfg_dir/config
fi
echo "# Networking" >>$cfg_dir/config
# see if the default network settings were already specified
lxc_network_type=`grep '^lxc.net.0.type' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
if [ -z "$lxc_network_type" ]; then
echo "lxc.net.0.type = veth" >>$cfg_dir/config
lxc_network_type=veth
fi
lxc_network_link=`grep '^lxc.net.0.link' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
if [ -z "$lxc_network_link" ]; then
echo "lxc.net.0.link = lxcbr0" >>$cfg_dir/config
lxc_network_link=lxcbr0
fi
lxc_network_hwaddr=`grep '^lxc.net.0.hwaddr' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
if [ -z "$lxc_network_hwaddr" ]; then
# generate a hwaddr for the container
# see http://sourceforge.net/tracker/?func=detail&aid=3411497&group_id=163076&atid=826303
local hwaddr="00:16:3e:`dd if=/dev/urandom bs=8 count=1 2>/dev/null |od -t x8 | \
head -n1 | awk '{print $2}' | cut -c1-6 | \
sed 's/\(..\)/\1:/g; s/.$//'`"
echo "lxc.net.0.hwaddr = $hwaddr" >>$cfg_dir/config
fi
lxc_network_flags=`grep '^lxc.net.0.flags' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
if [ -z "$lxc_network_flags" ]; then
echo "lxc.net.0.flags = up" >>$cfg_dir/config
fi
cat <<EOF >> $cfg_dir/config || die "unable to create $cfg_dir/config"
lxc.net.0.name = eth0
lxc.net.0.mtu = 1500
EOF
}
container_rootfs_clone()
{
if is_btrfs_subvolume $template_rootfs; then
# lxc-create already made $container_rootfs a btrfs subvolume, but
# in this case we want to snapshot the original subvolume so we we
# have to delete the one that lxc-create made
btrfs subvolume delete $container_rootfs
btrfs subvolume snapshot $template_rootfs $container_rootfs || die "btrfs clone template"
else
echo "Copying rootfs ..."
cp -axT $template_rootfs $container_rootfs || die "copy template"
fi
}
container_rootfs_repo_create()
{
echo "# LXC generated .repo file" >$1
echo "[$2]" >>$1
echo "name=Oracle Linux $container_release_major.$container_release_minor ($basearch)" >>$1
echo "baseurl=$3/" >>$1
echo "enabled=1" >>$1
echo "skip_if_unavailable=1" >>$1
if [ "$4" != "" ]; then
echo "gpgkey=$yum_url/RPM-GPG-KEY-oracle-ol$container_release_major" >>$1
echo "gpgcheck=1" >>$1
else
echo "gpgcheck=0" >>$1
fi
}
container_rootfs_dev_create()
{
# create required devices. note that /dev/console will be created by lxc
# or libvirt itself to be a symlink to the right pty.
# take care to not nuke /dev in case $container_rootfs isn't set
dev_path="$container_rootfs/dev"
if [ $container_rootfs != "/" -a -d $dev_path ]; then
rm -rf $dev_path
fi
mkdir -p $dev_path
if can_chcon; then
# ensure symlinks created in /dev have the right context
chcon -t device_t $dev_path
fi
mknod -m 666 $dev_path/null c 1 3
mknod -m 666 $dev_path/zero c 1 5
mknod -m 666 $dev_path/random c 1 8
mknod -m 666 $dev_path/urandom c 1 9
mkdir -m 755 $dev_path/pts
mkdir -m 1777 $dev_path/shm
mknod -m 666 $dev_path/tty c 5 0
mknod -m 666 $dev_path/tty1 c 4 1
mknod -m 666 $dev_path/tty2 c 4 2
mknod -m 666 $dev_path/tty3 c 4 3
mknod -m 666 $dev_path/tty4 c 4 4
mknod -m 666 $dev_path/full c 1 7
mknod -m 600 $dev_path/initctl p
# set selinux labels same as host
if can_chcon; then
for node in null zero random urandom pts shm \
tty tty0 tty1 tty2 tty3 tty4 full ;
do
chcon --reference /dev/$node $dev_path/$node 2>/dev/null
done
fi
}
container_rootfs_create()
{
if can_chcon; then
chcon --reference / $container_rootfs 2>/dev/null
fi
cmds="rpm wget yum"
if [ $container_release_major -lt "6" ]; then
if [ $host_distribution = "Ubuntu" -o $host_distribution = "Debian" ]; then
db_dump_cmd="db5.1_dump"
fi
if [ $host_distribution = "OracleServer" -o \
$host_distribution = "Fedora" ]; then
db_dump_cmd="db_dump"
fi
cmds="$cmds $db_dump_cmd file"
fi
for cmd in $cmds; do
which $cmd >/dev/null 2>&1
if [ $? -ne 0 ]; then
die "The $cmd command is required, please install it"
fi
done
mkdir -p @LOCALSTATEDIR@/lock/subsys
(
flock -x 9
if [ $? -ne 0 ]; then
die "The template is busy."
fi
echo "Yum installing release $container_release_major.$container_release_minor for $basearch"
if [ -n "$repourl" ]; then
yum_url=$repourl
else
yum_url=http://public-yum.oracle.com
fi
if [ $container_release_major = "4" -o $container_release_major = "5" ]; then
latest_L="el"
latest_U="EL"
else
latest_L="ol"
latest_U="OL"
fi
if [ -n "$baseurl" ]; then
# create .repo pointing at baseurl
repo="lxc-install"
mkdir -p $container_rootfs/etc/yum.repos.d
container_rootfs_repo_create \
$container_rootfs/etc/yum.repos.d/lxc-install.repo $repo $baseurl
else
# get public-yum repo file
if [ $container_release_major = "4" ]; then
repofile=public-yum-el4.repo
elif [ $container_release_major = "5" ]; then
repofile=public-yum-el5.repo
elif [ $container_release_major = "6" ]; then
repofile=public-yum-ol6.repo
elif [ $container_release_major = "7" ]; then
repofile=public-yum-ol7.repo
else
die "Unsupported release $container_release_major"
fi
mkdir -p $container_rootfs/etc/yum.repos.d
wget -q $yum_url/$repofile -O $container_rootfs/etc/yum.repos.d/$repofile
if [ $? -ne 0 ]; then
die "Unable to download repo file $yum_url/$repofile, release unavailable"
fi
# yum will take $basearch from host, so force the arch we want
sed -i "s|\$basearch|$basearch|" $container_rootfs/etc/yum.repos.d/$repofile
# replace url if they specified one
if [ -n "$repourl" ]; then
sed -i "s|baseurl=http://public-yum.oracle.com/repo|baseurl=$repourl/repo|" $container_rootfs/etc/yum.repos.d/$repofile
sed -i "s|gpgkey=http://public-yum.oracle.com|gpgkey=$repourl|" $container_rootfs/etc/yum.repos.d/$repofile
fi
# disable all repos, then enable the repo for the version we are installing.
if [ $container_release_minor = "latest" ]; then
repo=$latest_L""$container_release_major"_"$container_release_minor
elif [ $container_release_major = "7" ]; then
repo="ol"$container_release_major"_u"$container_release_minor"_base"
elif [ $container_release_major = "6" ]; then
if [ $container_release_minor = "0" ]; then
repo="ol"$container_release_major"_ga_base"
else
repo="ol"$container_release_major"_u"$container_release_minor"_base"
fi
elif [ $container_release_major = "5" ]; then
if [ $container_release_minor = "0" ]; then
repo="el"$container_release_major"_ga_base"
elif [ $container_release_minor -lt "6" ]; then
repo="el"$container_release_major"_u"$container_release_minor"_base"
else
repo="ol"$container_release_major"_u"$container_release_minor"_base"
fi
elif [ $container_release_major = "4" -a $container_release_minor -gt "5" ]; then
repo="el"$container_release_major"_u"$container_release_minor"_base"
else
die "Unsupported release $container_release_major.$container_release_minor"
fi
sed -i "s|enabled=1|enabled=0|" $container_rootfs/etc/yum.repos.d/$repofile
sed -i "/\[$repo\]/,/\[/ s/enabled=0/enabled=1/" $container_rootfs/etc/yum.repos.d/$repofile
fi
container_rootfs_dev_create
# don't put devpts,proc, nor sysfs in here, it will already be mounted for us by lxc/libvirt
echo "" >$container_rootfs/etc/fstab
# create rpm db, download and yum install minimal packages
mkdir -p $container_rootfs/var/lib/rpm
rpm --root $container_rootfs --initdb
yum_args="--installroot $container_rootfs --disablerepo=* --enablerepo=$repo -y --nogpgcheck"
min_pkgs="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils oraclelinux-release"
if [ $container_release_major -lt "6" ]; then
min_pkgs="$min_pkgs db4-utils"
fi
# we unshare the mount namespace because yum installing the ol4
# packages causes $rootfs/proc to be mounted on
lxc-unshare -s MOUNT yum -- $yum_args install $min_pkgs $user_pkgs
if [ $? -ne 0 ]; then
die "Failed to download and install the rootfs, aborting."
fi
# rsyslog and pam depend on coreutils for some common commands in
# their POSTIN scriptlets, but coreutils wasn't installed yet. now
# that coreutils is installed, reinstall the packages so their POSTIN
# runs right. similarly, libutempter depends on libselinux.so.1 when
# it runs /usr/sbin/groupadd, so reinstall it too
redo_pkgs=""
if [ $container_release_major = "5" ]; then
if [ $container_release_minor = "latest" ]; then
redo_pkgs="pam rsyslog libutempter"
elif [ $container_release_minor -lt 2 ]; then
redo_pkgs="pam"
elif [ $container_release_minor -lt 6 ]; then
redo_pkgs="pam rsyslog"
elif [ $container_release_minor -gt 5 ]; then
redo_pkgs="pam rsyslog libutempter"
fi
fi
# shadow utils fails on ol4 and ol6.1
if [ $container_release_major = "4" -o \
$container_release_major = "6" -a $container_release_minor = "1" ]; then
redo_pkgs="shadow-utils"
fi
if [ x"$redo_pkgs" != x ]; then
rpm --root $container_rootfs --nodeps -e $redo_pkgs
lxc-unshare -s MOUNT yum -- $yum_args install $redo_pkgs
if [ $? -ne 0 ]; then
die "Unable to reinstall packages"
fi
fi
# if installing from a baseurl, create a .repo that the container
# can use to update to _latest from http://public-yum.oracle.com
if [ -n "$baseurl" ]; then
container_rootfs_repo_create \
"$container_rootfs/etc/yum.repos.d/public-yum-"$latestL""$container_release_major".repo" \
$latest_L""$container_release_major"_latest" \
$yum_url"/repo/OracleLinux/"$latest_U""$container_release_major"/latest/$basearch" gpg
fi
# these distributions put the rpm database in a place the guest is
# not expecting it, so move it
if [ $host_distribution = "Ubuntu" -o $host_distribution = "Debian" ]; then
mv $container_rootfs/$HOME/.rpmdb/* $container_rootfs/var/lib/rpm
fi
# if the native rpm created the db with Hash version 9, we need to
# downgrade it to Hash version 8 for use with OL5.x
db_version=`file $container_rootfs/var/lib/rpm/Packages | \
grep -o 'version [0-9]*' |awk '{print $2}'`
if [ $container_release_major -lt "6" -a $db_version != "8" ]; then
echo "Fixing (downgrading) rpm database from version $db_version"
rm -f $container_rootfs/var/lib/rpm/__db*
for db in $container_rootfs/var/lib/rpm/* ; do
$db_dump_cmd $db |chroot $container_rootfs db_load /var/lib/rpm/`basename $db`.new
mv $db.new $db
done
fi
# the host rpm may not be the same as the guest, rebuild the db with
# the guest rpm version
echo "Rebuilding rpm database"
rm -f $container_rootfs/var/lib/rpm/__db*
chroot $container_rootfs rpm --rebuilddb >/dev/null 2>&1
) 9>@LOCALSTATEDIR@/lock/subsys/lxc-oracle-$name
if [ $? -ne 0 ]; then
exit 1
fi
}
container_release_get()
{
if [ -f $1/etc/oracle-release ]; then
container_release_version=`cat $1/etc/oracle-release |awk '/^Oracle/ {print $5}'`
container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'`
container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'`
elif grep -q "Enterprise Linux AS" $1/etc/redhat-release; then
container_release_major=`cat $1/etc/redhat-release |awk '{print $7}'`
container_release_minor=`cat $1/etc/redhat-release |awk '{print $10}' |tr -d ")"`
container_release_version="$container_release_major.$container_release_minor"
elif grep -q "Enterprise Linux Server" $1/etc/redhat-release; then
container_release_version=`cat $1/etc/redhat-release |awk '{print $7}'`
container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'`
container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'`
else
echo "Unable to determine container release version"
exit 1
fi
}
usage()
{
cat <<EOF
-a|--arch=<arch> architecture (ie. i386, x86_64)
-R|--release=<release> release to download for the new container
--rootfs=<path> rootfs path
-r|--rpms=<rpm name> additional rpms to install into container
-u|--url=<url> replace yum repo url (ie. Oracle public-yum mirror)
--baseurl=<url> use package repository (ie. file:///mnt)
arch and release must also be specified
-t|--templatefs=<path> copy/clone rootfs at path instead of downloading
-P|--patch=<path> only patch the rootfs at path for use as a container
-h|--help
Release is of the format "major.minor", for example "5.8", "6.3", or "6.latest"
This template supports Oracle Linux releases 4.6 - 7.0
EOF
return 0
}
options=$(getopt -o hp:n:a:R:r:u:t: -l help,rootfs:,path:,name:,arch:,release:,rpms:,url:,templatefs:,patch:,baseurl: -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
fi
eval set -- "$options"
while true
do
case "$1" in
-h|--help) usage $0 && exit 0;;
-p|--path) cfg_dir=$2; shift 2;;
--rootfs) container_rootfs=$2; shift 2;;
-n|--name) name=$2; shift 2;;
-a|--arch) arch=$2; shift 2;;
-R|--release) container_release_version=$2; shift 2;;
-r|--rpms) user_pkgs=$2; shift 2;;
-u|--url) repourl=$2; shift 2;;
-t|--templatefs) template_rootfs=$2; shift 2;;
--patch) patch_rootfs=$2; shift 2;;
--baseurl) baseurl=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
# make sure mandatory args are given and valid
if [ "$(id -u)" != "0" ]; then
echo "This script should be run as 'root'"
exit 1
fi
if [ -n "$baseurl" ]; then
if [ "$arch" = "" -o "$container_release_version" = "" ]; then
echo "The --arch and --release must be specified when using --baseurl"
usage
exit 1
fi
fi
if [ "$arch" = "" ]; then
arch=$(uname -m)
fi
if [ -n "$patch_rootfs" ]; then
container_rootfs="$patch_rootfs"
container_release_get $container_rootfs
container_rootfs_patch
exit 0
fi
if [ -z $name ]; then
echo "Container name must be given"
usage
exit 1
fi
if [ -z $cfg_dir ]; then
echo "Configuration directory must be given, check lxc-create"
usage
exit 1
fi
basearch=$arch
if [ "$arch" = "i686" ]; then
basearch="i386"
fi
if [ "$arch" != "i386" -a "$arch" != "x86_64" ]; then
echo "Bad architecture given, check lxc-create"
usage
exit 1
fi
if which lsb_release >/dev/null 2>&1; then
host_distribution=`lsb_release --id |awk '{print $3}'`
host_release_version=`lsb_release --release |awk '{print $2}'`
host_release_major=`echo $host_release_version |awk -F '.' '{print $1}'`
host_release_minor=`echo $host_release_version |awk -F '.' '{print $2}'`
else
if [ -f /etc/fedora-release ]; then
host_distribution="Fedora"
host_release_version=`cat /etc/fedora-release |awk '{print $3}'`
host_release_major=$host_release_version
host_release_minor=0
elif [ -f /etc/oracle-release ]; then
host_distribution="OracleServer"
host_release_version=`cat /etc/oracle-release |awk '{print $5}'`
host_release_major=`echo $host_release_version |awk -F '.' '{print $1}'`
host_release_minor=`echo $host_release_version |awk -F '.' '{print $2}'`
else
echo "Unable to determine host distribution, ensure lsb_release is installed"
exit 1
fi
fi
echo "Host is $host_distribution $host_release_version"
if [ -z "$container_rootfs" ]; then
container_rootfs="$cfg_dir/rootfs"
fi
if [ -n "$template_rootfs" ]; then
container_release_get $template_rootfs
else
if [ -z "$container_release_version" ]; then
if [ $host_distribution = "OracleServer" ]; then
container_release_version=$host_release_version
else
echo "No release specified with -R, defaulting to 6.5"
container_release_version="6.5"
fi
fi
container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'`
container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'`
fi
container_config_create
if [ -n "$template_rootfs" ]; then
container_rootfs_clone
else
container_rootfs_create
fi
container_release_get $container_rootfs
container_rootfs_configure
echo "Container : $container_rootfs"
echo "Config : $cfg_dir/config"
echo "Network : eth0 ($lxc_network_type) on $lxc_network_link"

384
templates/lxc-plamo.in Normal file
View File

@ -0,0 +1,384 @@
#!/bin/bash -eu
#
# template script for generating Plamo Linux container for LXC
#
#
# lxc: linux Container library
# Authors:
# KATOH Yasufumi <karma@jazz.email.ne.jp>
# TAMUKI Shoichi <tamuki@linet.gr.jp>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# ref. https://github.com/Ponce/lxc-slackware/blob/master/lxc-slackware
# lxc-ubuntu script
# Detect use under userns (unsupported)
for arg in "$@"; do
[ "$arg" = "--" ] && break
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
echo "This template can't be used for unprivileged containers." 1>&2
echo "You may want to try the \"download\" template instead." 1>&2
exit 1
fi
done
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
[ -r /etc/default/lxc ] && . /etc/default/lxc
DLSCHEME=${DLSCHEME:-"http"}
MIRRORSRV=${MIRRORSRV:-"repository.plamolinux.org"}
MIRRORPATH=${MIRRORPATH:-"/pub/linux/Plamo"}
CATEGORIES=${CATEGORIES-"00_base 01_minimum"}
EXTRACTGRS=${EXTRACTGRS-""}
IGNOREPKGS=${IGNOREPKGS-"grub kernel lilo linux_firmware microcode_ctl
cpufreqd cpufrequtils gpm ntp kmod"}
ADDONPKGS=${ADDONPKGS-"`echo contrib/Hamradio/{morse,qrq}`"}
download_plamo() {
# check the mini plamo was not already downloaded
if ! mkdir -p $ptcache ; then
echo "Failed to create '$ptcache' directory."
return 1
fi
# download a mini plamo into a cache
echo "Downloading Plamo-$release minimal..."
cd $ptcache
case $DLSCHEME in http) depth=2 ;; ftp) depth=3 ;; esac
rej=${IGNOREPKGS%% *} ; [ -n "$rej" ] && rej="$rej-*"
if [ `echo $IGNOREPKGS | wc -w` -gt 1 ] ; then
for p in ${IGNOREPKGS#* } ; do rej="$rej,$p-*" ; done
fi
for i in $CATEGORIES ; do
wget -nv -e robots=off -r -l $depth -nd -A .tgz,.txz -R "$rej" \
-I $MIRRORPATH/Plamo-$release/$arch/plamo/$i \
-X $MIRRORPATH/Plamo-$release/$arch/plamo/$i/old \
$DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/plamo/$i
if [ $? -ne 0 ] ; then
echo "Failed to download the rootfs, aborting."
return 1
fi
done
for i in $EXTRACTGRS ; do
wget -nv -e robots=off -r -l $depth -nd -A .tgz,.txz -R "$rej" \
-I $MIRRORPATH/Plamo-$release/$arch/contrib/$i \
-X $MIRRORPATH/Plamo-$release/$arch/contrib/$i/old \
$DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/contrib/$i
if [ $? -ne 0 ] ; then
echo "Failed to download the rootfs, aborting."
return 1
fi
done
for p in $ADDONPKGS ; do
wget -nv -e robots=off -r -l $depth -nd -A "`basename $p`-*" \
-I $MIRRORPATH/Plamo-$release/$arch/`dirname $p` \
-X $MIRRORPATH/Plamo-$release/$arch/`dirname $p`/old \
$DLSCHEME://$MIRRORSRV$MIRRORPATH/Plamo-$release/$arch/`dirname $p`
if [ $? -ne 0 ] ; then
echo "Failed to download the rootfs, aborting."
return 1
fi
done
mv $ptcache $dlcache
echo "Download complete."
return 0
}
copy_plamo() {
# make a local copy of the mini plamo
echo "Copying $rtcache to $rootfs..."
mkdir -p $rootfs
find $rtcache -mindepth 1 -maxdepth 1 -exec cp -a {} $rootfs \; || return 1
return 0
}
install_plamo() {
mkdir -p @LOCALSTATEDIR@/lock/subsys
(
if ! flock -n 9 ; then
echo "Cache repository is busy."
return 1
fi
echo "Checking cache download in $dlcache..."
if [ ! -d $dlcache ] ; then
if ! download_plamo ; then
echo "Failed to download plamo $release base packages."
return 1
fi
fi
# install "installpkg" command temporarily with static linked tar
# command into the lxc cache directory to keep the original uid/
# gid of files/directories.
echo "Installing 'installpkg' command into $dlcache/sbin..."
( cd $dlcache ; tar xpJf hdsetup-*.txz ; rm -rf tmp usr var )
sed -i "/ldconfig/!s@/sbin@$dlcache&@g" $dlcache/sbin/installpkg*
PATH=$dlcache/sbin:$PATH
echo "Installing packages to $rtcache..."
if [ ! -d $rtcache ] ; then
mkdir -p $rtcache
for p in `ls -cr $dlcache/*.t?z` ; do
installpkg -root $rtcache -priority ADD $p
done
fi
echo "Copy $rtcache to $rootfs..."
if ! copy_plamo ; then
echo "Failed to copy rootfs."
return 1
fi
return 0
) 9> @LOCALSTATEDIR@/lock/subsys/lxc-plamo
}
configure_plamo() {
# suppress log level output for udev
sed -i 's/="err"/=0/' $rootfs/etc/udev/udev.conf
# /etc/fstab
cat <<- "EOF" > $rootfs/etc/fstab
none /proc proc defaults 0 0
none /sys sysfs defaults 0 0
none /dev tmpfs defaults 0 0
none /tmp tmpfs defaults 0 0
none /dev/pts devpts gid=5,mode=620 0 0
none /proc/bus/usb usbfs noauto 0 0
none /var/lib/nfs/rpc_pipefs rpc_pipefs defaults 0 0
EOF
# /etc/inittab
cat <<- "EOF" | patch $rootfs/etc/inittab
32,33c32,33
< # What to do when power fails (shutdown to single user).
< pf::powerfail:/sbin/shutdown -f +5 "THE POWER IS FAILING"
---
> # What to do when power fails (shutdown).
> pf::powerfail:/sbin/shutdown -h +0 "THE POWER IS FAILING"
47a48
> 1:1235:respawn:/sbin/agetty 38400 console
52,53d52
< c5:1235:respawn:/sbin/agetty 38400 tty5 linux
< c6:12345:respawn:/sbin/agetty 38400 tty6 linux
EOF
# set the hostname
echo "$name" > $rootfs/etc/HOSTNAME
# set minimal hosts
echo "127.0.0.1 localhost $name" > $rootfs/etc/hosts
# configure the network using the dhcp
echo "DHCP" > $rootfs/var/run/inet1-scheme
# localtime (JST)
ln -s ../usr/share/zoneinfo/Asia/Tokyo $rootfs/etc/localtime
# disable pam_loginuid.so in /etc/pam.d/login (for libvirt's lxc driver)
sed -i '/pam_loginuid/s/^/#/' $rootfs/etc/pam.d/login
# glibc configure
mv $rootfs/etc/ld.so.conf{.new,}
chroot $rootfs ldconfig
# delete unnecessary process from rc.S
ed - $rootfs/etc/rc.d/rc.S <<- "EOF"
/^mount -w -n -t proc/;/^mkdir \/dev\/shm/-1d
/^mknod \/dev\/null/;/^# Clean \/etc\/mtab/-2d
/^# copy the rules/;/^# Set the hostname/-1d
/^# Check the integrity/;/^# Clean up temporary/-1d
w
EOF
# delete unnecessary process from rc.M
ed - $rootfs/etc/rc.d/rc.M <<- "EOF"
/^# Screen blanks/;/^# Initialize ip6tables/-1d
/^# Initialize sysctl/;/^echo "Starting services/-1d
/^sync/;/^# All done/-1d
w
EOF
# delete unnecessary process from rc.6
ed - $rootfs/etc/rc.d/rc.6 <<- "EOF"
/^# Save system time/;/^# Unmount any remote filesystems/-1d
/^# Turn off swap/;/^# See if this is a powerfail situation/-1d
w
EOF
# /etc/rc.d/rc.inet1.tradnet
head -n-93 $rootfs/sbin/netconfig.tradnet > /tmp/netconfig.rconly
cat <<- EOF >> /tmp/netconfig.rconly
PCMCIA=n
RC=$rootfs/etc/rc.d/rc.inet1.tradnet
IFCONFIG=sbin/ifconfig
ROUTE=sbin/route
INET1SCHEME=var/run/inet1-scheme
IPADDR=127.0.0.1
NETWORK=127.0.0.0
DHCPCD=usr/sbin/dhclient
LOOPBACK=y
make_config_file
EOF
rm -f $rootfs/etc/rc.d/rc.inet1.tradnet
sh /tmp/netconfig.rconly
rm -f /tmp/netconfig.rconly
sed -i '/cmdline/s/if/& false \&\&/' $rootfs/etc/rc.d/rc.inet1.tradnet
# /etc/rc.d/rc.inet2
sed -i '/rpc.mountd/s/^/#/' $rootfs/etc/rc.d/rc.inet2
sed -i '/modprobe/s/^/#/' $rootfs/etc/rc.d/rc.inet2
# configure to start only the minimum of service
chmod 644 $rootfs/etc/rc.d/init.d/saslauthd
chmod 644 $rootfs/etc/rc.d/init.d/open-iscsi
rm -f $rootfs/etc/rc.d/init.d/postfix
rm -f $rootfs/var/log/initpkg/shadow
return 0
}
copy_configuration() {
ret=0
cat <<- EOF >> $path/config || let ret++
lxc.uts.name = $name
lxc.arch = $arch
EOF
if [ -f "@LXCTEMPLATECONFIG@/plamo.common.conf" ] ; then
cat <<- "EOF" >> $path/config || let ret++
lxc.include = @LXCTEMPLATECONFIG@/plamo.common.conf
EOF
fi
if [ $ret -ne 0 ] ; then
echo "Failed to add configuration."
return 1
fi
return 0
}
post_process() {
# nothing do in Plamo Linux
true
}
do_bindhome() {
# bind-mount the user's path into the container's /home
h=`getent passwd $bindhome | cut -d: -f6`
mkdir -p $rootfs/$h
echo "lxc.mount.entry = $h $rootfs/$h none bind 0 0" >> $path/config
# copy /etc/passwd, /etc/shadow, and /etc/group entries into container
if ! pwd=`getent passwd $bindhome` ; then
echo "Warning: failed to copy password entry for $bindhome."
else
echo $pwd >> $rootfs/etc/passwd
fi
echo `getent shadow $bindhome` >> $rootfs/etc/shadow
}
cleanup() {
[ -d $dlcache -a -d $rtcache ] || return 0
# lock, so we won't purge while someone is creating a repository
(
if ! flock -n 9 ; then
echo "Cache repository is busy."
return 1
fi
echo "Purging the download cache..."
rm -rf --one-file-system $dlcache $rtcache || return 1
echo "Done."
return 0
) 9> @LOCALSTATEDIR@/lock/subsys/lxc-plamo
}
usage() {
cat <<- EOF
$prog [-h|--help] -p|--path=<path> -n|--name=<name> --rootfs=<rootfs>
[-c|--clean] [-r|--release=<release>] [-a|--arch=<arch>]
[-b|--bindhome=<user>]
release: $release
arch: x86 or x86_64: defaults to host arch
bindhome: bind <user>'s home into the container
EOF
}
prog=`basename $0`
path="" ; name="" ; rootfs=""
clean=0
release=${release:-6.x}
arch=`uname -m | sed 's/i.86/x86/'` ; hostarch=$arch
bindhome=""
sopts=hp:n:cr:a:b:
lopts=help,path:,name:,rootfs:,clean,release:,arch:,bindhome:
if ! options=`getopt -o $sopts -l $lopts -- "$@"` ; then
usage
exit 1
fi
eval set -- "$options"
while true ; do
case "$1" in
-h|--help) usage && exit 0 ;;
-p|--path) path=$2 ; shift 2 ;;
-n|--name) name=$2 ; shift 2 ;;
--rootfs) rootfs=$2 ; shift 2 ;;
-c|--clean) clean=1 ; shift 1 ;;
-r|--release) release=$2 ; shift 2 ;;
-a|--arch) arch=$2 ; shift 2 ;;
-b|--bindhome) bindhome=$2 ; shift 2 ;;
--) shift 1 ; break ;;
*) break ;;
esac
done
if [ $clean -eq 1 -a -z "$path" ] ; then
cleanup || exit 1
exit 0
fi
if [ $hostarch == "x86" -a $arch == "x86_64" ] ; then
echo "Can't create x86_64 container on x86."
exit 1
fi
if [ -z "$path" ] ; then
echo "'path' parameter is required."
exit 1
fi
if [ -z "$name" ] ; then
echo "'name' parameter is required."
exit 1
fi
if [ `id -u` -ne 0 ] ; then
echo "This script should be run as 'root'."
exit 1
fi
cache="${LXC_CACHE_PATH:-@LOCALSTATEDIR@/cache/lxc}"
ptcache=$cache/partial-${prog##*-}-$release-$arch
dlcache=$cache/cache-${prog##*-}-$release-$arch
rtcache=$cache/rootfs-${prog##*-}-$release-$arch
if [ -z "$rootfs" ] ; then
if grep -q "^lxc.rootfs.path" $path/config ; then
rootfs=`awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config`
else
rootfs=$path/rootfs
fi
fi
if ! install_plamo ; then
echo "Failed to install plamo $release."
exit 1
fi
if ! configure_plamo ; then
echo "Failed to configure plamo $release for a container."
exit 1
fi
if ! copy_configuration ; then
echo "Failed to write configuration file."
exit 1
fi
post_process
if [ -n "$bindhome" ] ; then
do_bindhome
fi
if [ $clean -eq 1 ] ; then
cleanup || exit 1
exit 0
fi

484
templates/lxc-pld.in Normal file
View File

@ -0,0 +1,484 @@
#!/bin/sh
#
# template script for generating PLD Linux container for LXC
#
#
# lxc: Linux Container library
# Authors:
# Elan Ruusamäe <glen@pld-linux.org>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Detect use under userns (unsupported)
for arg in "$@"; do
[ "$arg" = "--" ] && break
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
echo "This template can't be used for unprivileged containers." 1>&2
echo "You may want to try the \"download\" template instead." 1>&2
exit 1
fi
done
# Configuration
arch=$(uname -m)
cache_base=@LOCALSTATEDIR@/cache/lxc/pld/$arch
default_path=@LXCPATH@
if [ -e /etc/os-release ]; then
# This is a shell friendly configuration file. We can just source it.
# What we're looking for in here is the ID, VERSION_ID and the CPE_NAME
. /etc/os-release
echo "Host CPE ID from /etc/os-release: ${CPE_NAME}"
fi
if [ "${CPE_NAME}" != "" -a "${ID}" = "pld" -a "${VERSION_ID}" != "" ]; then
pld_host_ver=${VERSION_ID}
is_pld=true
elif [ -e /etc/pld-release ]; then
# Only if all other methods fail, try to parse the pld-release file.
pld_host_ver=$(sed -e '/PLD /!d' -e 's/^\([0-9.]*\)\sPLD.*/\1/' < /etc/pld-release)
if [ "$pld_host_ver" != "" ]; then
is_pld=true
fi
fi
# Map a few architectures to their generic PLD Linux repository archs.
case "$pld_host_ver:$arch" in
3.0:i586) arch=i486 ;;
esac
configure_pld()
{
# disable selinux
mkdir -p $rootfs_path/selinux
echo 0 > $rootfs_path/selinux/enforce
# configure the network using the dhcp
sed -i -e "s/^HOSTNAME=.*/HOSTNAME=${utsname}/" ${rootfs_path}/etc/sysconfig/network
# set hostname on systemd
if [ $release = "3.0" ]; then
echo "${utsname}" > ${rootfs_path}/etc/hostname
fi
# set minimal hosts
test -e $rootfs_path/etc/hosts || \
cat <<EOF > $rootfs_path/etc/hosts
127.0.0.1 localhost.localdomain localhost $utsname
::1 localhost6.localdomain6 localhost6
EOF
dev_path="${rootfs_path}/dev"
rm -rf $dev_path
mkdir -p $dev_path
mknod -m 666 ${dev_path}/null c 1 3
mknod -m 666 ${dev_path}/zero c 1 5
mknod -m 666 ${dev_path}/random c 1 8
mknod -m 666 ${dev_path}/urandom c 1 9
mkdir -m 755 ${dev_path}/pts
mkdir -m 1777 ${dev_path}/shm
mknod -m 666 ${dev_path}/tty c 5 0
mknod -m 666 ${dev_path}/tty0 c 4 0
mknod -m 666 ${dev_path}/tty1 c 4 1
mknod -m 666 ${dev_path}/tty2 c 4 2
mknod -m 666 ${dev_path}/tty3 c 4 3
mknod -m 666 ${dev_path}/tty4 c 4 4
mknod -m 600 ${dev_path}/console c 5 1
mknod -m 666 ${dev_path}/full c 1 7
mknod -m 600 ${dev_path}/initctl p
mknod -m 666 ${dev_path}/ptmx c 5 2
if [ -n "${root_password}" ]; then
echo "setting root passwd to $root_password"
echo "root:$root_password" | chroot $rootfs_path chpasswd
fi
return 0
}
configure_pld_init()
{
# default powerfail action waits 2 minutes. for lxc we want it immediately
sed -i -e '/^pf::powerfail:/ s,/sbin/shutdown.*,/sbin/halt,' ${rootfs_path}/etc/inittab
}
configure_pld_systemd()
{
unlink ${rootfs_path}/etc/systemd/system/default.target
chroot ${rootfs_path} ln -s /dev/null /etc/systemd/system/udev.service
chroot ${rootfs_path} ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
# Actually, the After=dev-%i.device line does not appear in the
# Fedora 17 or Fedora 18 systemd getty@.service file. It may be left
# over from an earlier version and it's not doing any harm. We do need
# to disable the "ConditionalPathExists=/dev/tty0" line or no gettys are
# started on the ttys in the container. Lets do it in an override copy of
# the service so it can still pass rpm verifies and not be automatically
# updated by a new systemd version. -- mhw /\/\|=mhw=|\/\/
sed -e 's/^ConditionPathExists=/# ConditionPathExists=/' \
-e 's/After=dev-%i.device/After=/' \
< ${rootfs_path}/lib/systemd/system/getty@.service \
> ${rootfs_path}/etc/systemd/system/getty@.service
# Setup getty service on the 4 ttys we are going to allow in the
# default config. Number should match lxc.tty.max
for i in 1 2 3 4; do
ln -sf ../getty@.service ${rootfs_path}/etc/systemd/system/getty.target.wants/getty@tty${i}.service
done
}
download_pld()
{
# check the mini pld was not already downloaded
INSTALL_ROOT=$cache/partial
mkdir -p $INSTALL_ROOT
if [ $? -ne 0 ]; then
echo "Failed to create '$INSTALL_ROOT' directory"
return 1
fi
# download a mini pld into a cache
echo "Downloading PLD Linux minimal ..."
POLDEK="poldek --root $INSTALL_ROOT --noask --nohold --noignore"
PKG_LIST="basesystem filesystem pld-release rpm poldek vserver-packages rc-scripts pwdutils mingetty"
mkdir -p $INSTALL_ROOT@LOCALSTATEDIR@/lib/rpm
rpm --root $INSTALL_ROOT --initdb
$POLDEK -u $PKG_LIST
if [ $? -ne 0 ]; then
echo "Failed to download the rootfs, aborting."
return 1
fi
mv "$INSTALL_ROOT" "$cache/rootfs"
echo "Download complete."
return 0
}
copy_pld()
{
# make a local copy of the minipld
echo -n "Copying rootfs to $rootfs_path ..."
cp -a $cache/rootfs/* $rootfs_path || return 1
return 0
}
update_pld()
{
POLDEK="poldek --root $cache/rootfs --noask"
$POLDEK --upgrade-dist
}
install_pld()
{
mkdir -p @LOCALSTATEDIR@/lock/subsys/
(
flock -x 9
if [ $? -ne 0 ]; then
echo "Cache repository is busy."
return 1
fi
echo "Checking cache download in $cache/rootfs ... "
if [ ! -e "$cache/rootfs" ]; then
download_pld
if [ $? -ne 0 ]; then
echo "Failed to download 'pld base'"
return 1
fi
else
echo "Cache found. Updating..."
update_pld
if [ $? -ne 0 ]; then
echo "Failed to update 'pld base', continuing with last known good cache"
else
echo "Update finished"
fi
fi
echo "Copy $cache/rootfs to $rootfs_path ... "
copy_pld
if [ $? -ne 0 ]; then
echo "Failed to copy rootfs"
return 1
fi
return 0
) 9>@LOCALSTATEDIR@/lock/subsys/lxc-pld
return $?
}
copy_configuration()
{
mkdir -p $config_path
grep -q "^lxc.rootfs.path" $config_path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs_path" >> $config_path/config
cat <<EOF >> $config_path/config
# Most of below settings should be taken as defaults from
# lxc.include = /usr/share/lxc/config/common.conf
lxc.uts.name = $utsname
lxc.tty.max = 4
lxc.pty.max = 1024
# Consider if below line is right for systemd container
lxc.mount.fstab = $config_path/fstab
lxc.cap.drop = sys_module mac_admin mac_override sys_time
lxc.autodev = $auto_dev
# When using LXC with apparmor, uncomment the next line to run unconfined:
#lxc.apparmor.profile = unconfined
## Devices
# Allow all devices
#lxc.cgroup.devices.allow = a
# Deny all devices
lxc.cgroup.devices.deny = a
# Allow to mknod all devices (but not using them)
lxc.cgroup.devices.allow = c *:* m
lxc.cgroup.devices.allow = b *:* m
# /dev/null and zero
lxc.cgroup.devices.allow = c 1:3 rwm
lxc.cgroup.devices.allow = c 1:5 rwm
# consoles
lxc.cgroup.devices.allow = c 5:1 rwm
lxc.cgroup.devices.allow = c 5:0 rwm
lxc.cgroup.devices.allow = c 4:0 rwm
lxc.cgroup.devices.allow = c 4:1 rwm
# /dev/{,u}random
lxc.cgroup.devices.allow = c 1:9 rwm
lxc.cgroup.devices.allow = c 1:8 rwm
lxc.cgroup.devices.allow = c 136:* rwm
lxc.cgroup.devices.allow = c 5:2 rwm
# rtc
lxc.cgroup.devices.allow = c 254:0 rm
EOF
cat <<EOF > $config_path/fstab
proc proc proc nodev,noexec,nosuid 0 0
sysfs sys sysfs defaults 0 0
EOF
if [ $? -ne 0 ]; then
echo "Failed to add configuration"
return 1
fi
return 0
}
clean()
{
if [ ! -e $cache ]; then
exit 0
fi
# lock, so we won't purge while someone is creating a repository
(
flock -x 9
if [ $? != 0 ]; then
echo "Cache repository is busy."
exit 1
fi
echo -n "Purging the download cache for PLD Linux $release..."
rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
exit 0
) 9>@LOCALSTATEDIR@/lock/subsys/lxc-pld
}
usage()
{
cat <<EOF
usage:
$1 -n|--name=<container_name>
[-p|--path=<path>] [-c|--clean] [-R|--release=<PLD Release>] [--fqdn=<network name of container>] [-A|--arch=<arch of the container>]
[-h|--help]
Mandatory args:
-n,--name container name, used to as an identifier for that container from now on
Optional args:
-p,--path path to where the container will be created, defaults to @LXCPATH@. The container config will go under @LXCPATH@ in that case
--rootfs path for actual rootfs.
-c,--clean clean the cache
-R,--release PLD Linux release for the new container. if the host is PLD Linux, then it will default to the host's release.
--fqdn fully qualified domain name (FQDN) for DNS and system naming
-A,--arch NOT USED YET. Define what arch the container will be [i686,x86_64]
-h,--help print this help
EOF
return 0
}
options=$(getopt -o hp:n:cR: -l help,path:,rootfs:,name:,clean,release:,fqdn: -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
fi
eval set -- "$options"
while :; do
case "$1" in
-h|--help) usage $0 && exit 0;;
-p|--path) path=$2; shift 2;;
--rootfs) rootfs=$2; shift 2;;
-n|--name) name=$2; shift 2;;
-c|--clean) clean=$2; shift 2;;
-R|--release) release=$2; shift 2;;
--fqdn) utsname=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
if [ ! -z "$clean" -a -z "$path" ]; then
clean || exit 1
exit 0
fi
if [ -z "${utsname}" ]; then
utsname=${name}
fi
# This follows a standard "resolver" convention that an FQDN must have
# at least two dots or it is considered a local relative host name.
# If it doesn't, append the dns domain name of the host system.
#
# This changes one significant behavior when running
# "lxc_create -n Container_Name" without using the
# --fqdn option.
#
# Old behavior:
# utsname and hostname = Container_Name
# New behavior:
# utsname and hostname = Container_Name.Domain_Name
if [ $(expr "$utsname" : '.*\..*\.') = 0 ]; then
if [ -n "$(dnsdomainname)" ]; then
utsname=${utsname}.$(dnsdomainname)
fi
fi
needed_pkgs=""
type poldek >/dev/null 2>&1
if [ $? -ne 0 ]; then
needed_pkgs="poldek $needed_pkgs"
fi
#type curl >/dev/null 2>&1
#if [ $? -ne 0 ]; then
# needed_pkgs="curl $needed_pkgs"
#fi
if [ -n "$needed_pkgs" ]; then
echo "Missing commands: $needed_pkgs"
echo "Please install these using \"sudo poldek -u $needed_pkgs\""
exit 1
fi
if [ -z "$path" ]; then
path=$default_path/$name
fi
if [ -z "$release" ]; then
if [ "$is_pld" -a "$pld_host_ver" ]; then
release=$pld_host_ver
else
echo "This is not a PLD Linux host and release missing, defaulting to 3.0. use -R|--release to specify release"
release=3.0
fi
fi
# pld th have systemd. We need autodev enabled to keep systemd from causing problems.
if [ $release = 3.0 ]; then
auto_dev="0"
else
auto_dev="0"
fi
if [ "$(id -u)" != "0" ]; then
echo "This script should be run as 'root'"
exit 1
fi
if [ -z "$rootfs" ]; then
rootfs_path=$path/rootfs
# check for 'lxc.rootfs.path' passed in through default config by lxc-create
# TODO: should be lxc.rootfs.mount used instead?
if grep -q '^lxc.rootfs.path' $path/config 2>/dev/null ; then
rootfs_path=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $path/config)
fi
else
rootfs_path=$rootfs
fi
config_path=$default_path/$name
cache=$cache_base/$release
revert()
{
echo "Interrupted, so cleaning up"
lxc-destroy -n $name
# maybe was interrupted before copy config
rm -rf $path
rm -rf $default_path/$name
echo "exiting..."
exit 1
}
trap revert SIGHUP SIGINT SIGTERM
copy_configuration
if [ $? -ne 0 ]; then
echo "Failed write configuration file"
exit 1
fi
install_pld
if [ $? -ne 0 ]; then
echo "Failed to install PLD Linux"
exit 1
fi
configure_pld
if [ $? -ne 0 ]; then
echo "Failed to configure PLD Linux for a container"
exit 1
fi
# If the systemd configuration directory exists - set it up for what we need.
if [ -d ${rootfs_path}/etc/systemd/system ]; then
configure_pld_systemd
fi
# This configuration (rc.sysinit) is not inconsistent with the systemd stuff
# above and may actually coexist on some upgraded systems. Let's just make
# sure that, if it exists, we update this file, even if it's not used...
if [ -f ${rootfs_path}/etc/rc.sysinit ]; then
configure_pld_init
fi
if [ ! -z $clean ]; then
clean || exit 1
exit 0
fi
echo "container rootfs and config created"

513
templates/lxc-sabayon.in Normal file
View File

@ -0,0 +1,513 @@
#!/bin/bash
# vim: set ts=4 sw=4 expandtab
# Exit on error and treat unset variables as an error.
set -eu
#
# LXC template for Sabayon OS, based of Alpine script.
#
# Authors:
# Geaaru <geaaru@gmail.com>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#=========================== Constants ============================#
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
readonly LOCAL_STATE_DIR='@LOCALSTATEDIR@'
readonly LXC_TEMPLATE_CONFIG='@LXCTEMPLATECONFIG@'
# Temporary static MIRROR LIST. I will get list from online path on the near future.
readonly MIRRORS_LIST="
http://mirror.it.sabayon.org/
http://dl.sabayon.org/
ftp://ftp.klid.dk/sabayonlinux/
http://ftp.fsn.hu/pub/linux/distributions/sabayon/
http://ftp.cc.uoc.gr/mirrors/linux/SabayonLinux/
http://ftp.rnl.ist.utl.pt/pub/sabayon/
ftp://ftp.nluug.nl/pub/os/Linux/distr/sabayonlinux/
http://mirror.internode.on.net/pub/sabayon/
http://mirror.yandex.ru/sabayon/
http://sabayon.c3sl.ufpr.br/
http://mirror.clarkson.edu/sabayon/
http://na.mirror.garr.it/mirrors/sabayonlinux/"
#======================== Global variables ========================#
# Clean variables and set defaults.
arch="$(uname -m)"
debug='no'
flush_cache='no'
mirror_url=
name=
path=
release="DAILY"
rootfs=
unprivileged=false
mapped_uid=
mapped_gid=
flush_owner=false
#======================== Helper Functions ========================#
usage() {
cat <<-EOF
Template specific options can be passed to lxc-create after a '--' like this:
lxc-create --name=NAME [lxc-create-options] -- [template-options]
Template options:
-a ARCH, --arch=ARCH The container architecture (e.g. x86_64, armv7); defaults
to the host arch.
-d, --debug Run this script in a debug mode (set -x and wget w/o -q).
-m URL --mirror=URL The Sabayon mirror to use; defaults to random mirror.
-u, --unprivileged Tuning of rootfs for unprivileged containers.
-r, --release Identify release to use. Default is DAILY.
--mapped-gid Group Id to use on unprivileged container
(based of value present on file /etc/subgid).
--mapped-uid User Id to use on unprivileged container
(based of value present on file /etc/subuid)
--flush-owner Only for directly creation of unprivileged containers
through lxc-create command. Execute fuidshift command.
Require --mapped-gid,--mapped-uid and --unprivileged
options.
Environment variables:
RELEASE Release version of Sabayon. Default is ${RELEASE}.
EOF
}
random_mirror_url() {
local url=""
if [ $arch == 'amd64' ] ; then
url=$(echo $MIRRORS_LIST | sed -e 's/ /\n/g' | sort -R --random-source=/dev/urandom | head -n 1)
else
if [ $arch == 'armv7l' ] ; then
# Currently armv7l tarball is not on sabayon mirrored tree.
url="https://dockerbuilder.sabayon.org/"
fi
fi
[ -n "$url" ] && echo "$url"
}
die() {
local retval=$1; shift
echo -e "==> $@\n"
exit $retval
}
einfo() {
echo -e "==> $@\n"
}
fetch() {
if [ "$debug" = 'yes' ]; then
wget -T 10 -O - $@
else
wget -T 10 -O - -q $@
fi
}
parse_arch() {
case "$1" in
x86_64 | amd64) echo 'amd64';;
armv7 | armv7l) echo 'armv7l';;
#arm*) echo 'armhf';;
*) return 1;;
esac
}
run_exclusively() {
local lock_name="$1"
local timeout=$2
local method=$3
shift 3
mkdir -p "$LOCAL_STATE_DIR/lock/subsys"
local retval
{
echo -n "Obtaining an exclusive lock..."
if ! flock -x 9; then
echo ' failed.'
return 1
fi
echo ' done'
${method} $@
retval=$?
} 9> "$LOCAL_STATE_DIR/lock/subsys/lxc-sabayon-$lock_name"
return $retval
}
create_url () {
local url=""
# Example of amd64 tarball url
# http://mirror.yandex.ru/sabayon/iso/daily/Sabayon_Linux_DAILY_amd64_tarball.tar.gz
if [ $arch == 'amd64' ] ; then
if [ $release = 'DAILY' ] ; then
url="${MIRROR_URL}iso/daily/Sabayon_Linux_DAILY_amd64_tarball.tar.gz"
else
url="${MIRROR_URL}iso/monthly/Sabayon_Linux_${release}_amd64_tarball.tar.gz"
fi
else
# https://dockerbuilder.sabayon.org/Sabayon_Linux_16_armv7l.tar.bz2
if [ $arch == 'armv7l' ] ; then
# Currently $arch tarball is not on sabayon mirrored tree.
url="${MIRROR_URL}Sabayon_Linux_16_armv7l.tar.bz2"
fi
fi
echo $url
}
#=========================== Configure ===========================#
unprivileged_rootfs() {
pushd ${rootfs}/etc/systemd/system
# Disable systemd-journald-audit.socket because it seems that doesn't
# start correctly on unprivileged container
ln -s /dev/null systemd-journald-audit.socket
# Disable systemd-remount-fs.service because on unprivileged container
# systemd can't remount filesystem
ln -s /dev/null systemd-remount-fs.service
# Remove mount of FUSE Control File system
ln -s /dev/null sys-fs-fuse-connections.mount
# Change execution of service systemd-sysctl to avoid errors.
mkdir systemd-sysctl.service.d
cat <<EOF > systemd-sysctl.service.d/00gentoo.conf
[Service]
ExecStart=
ExecStart=/usr/lib/systemd/systemd-sysctl --prefix=/etc/sysctl.d/
EOF
# Disable mount of hugepages
ln -s /dev/null dev-hugepages.mount
popd
pushd ${rootfs}
# Disable sabayon-anti-fork-bomb limits (already apply to lxc container manager)
sed -i -e 's/^*/#*/g' ./etc/security/limits.d/00-sabayon-anti-fork-bomb.conf || return 1
sed -i -e 's/^root/#root/g' ./etc/security/limits.d/00-sabayon-anti-fork-bomb.conf || return 1
popd
return 0
}
unprivileged_shift_owner () {
# I use /usr/bin/fuidshift from LXD project.
einfo "Executing: fuidshift ${rootfs} u:0:${mapped_uid}:65536 g:0:${mapped_gid}:65536 ..."
fuidshift ${rootfs} u:0:${mapped_uid}:65536 g:0:${mapped_gid}:65536 ||
die 1 "Error on change owners of ${rootfs} directory"
einfo "Done."
# Fix permission of container directory
chmod a+rx ${path}
return 0
}
systemd_container_tuning () {
# To avoid error on start systemd-tmpfiles-setup service
# it is needed clean journal directory
rm -rf ${rootfs}/var/log/journal/
# Remove LVM service. Normally not needed on container system.
rm -rf ${rootfs}/etc/systemd/system/sysinit.target.wants/lvm2-lvmetad.service
# Comment unneeded entry on /etc/fstab
sed -e 's/\/dev/#\/dev/g' -i ${rootfs}/etc/fstab
# Fix this stupid error until fix is available on sabayon image
# /usr/lib/systemd/system-generators/gentoo-local-generator: line 4: cd: /etc/local.d: No such file or directory
mkdir ${rootfs}/etc/local.d/
mkdir ${rootfs}/etc/systemd/system/NetworkManager.service.d/
cat <<EOF > ${rootfs}/etc/systemd/system/NetworkManager.service.d/override.conf
[Service]
ExecStartPre=-/bin/ip -4 link set dev eth0 down
EOF
chmod 644 ${rootfs}/etc/systemd/system/NetworkManager.service.d/override.conf
return 0
}
configure_container() {
local config="$1"
local hostname="$2"
local arch="$3"
local privileged_options=""
local unprivileged_options=""
if [[ $unprivileged && $unprivileged == true ]] ; then
if [[ $flush_owner == true ]] ; then
unprivileged_options="
lxc.idmap = u 0 ${mapped_uid} 65536
lxc.idmap = g 0 ${mapped_gid} 65536
"
fi
unprivileged_options="
$unprivileged_options
# Force use of cgroup v1. Currently systemd doesn't support
# correctly cgroup v2. See: https://github.com/lxc/lxc/issues/1669
# about discussion of default-hierarchy option.
lxc.init.cmd = /sbin/init systemd.legacy_systemd_cgroup_controller=yes
# Include common configuration.
lxc.include = $LXC_TEMPLATE_CONFIG/sabayon.userns.conf
"
else
privileged_options="
## Allow any mknod (but not reading/writing the node)
lxc.cgroup.devices.allow = b *:* m
lxc.cgroup.devices.allow = c *:* m
### /dev/pts/*
lxc.cgroup.devices.allow = c 136:* rwm
### /dev/tty
lxc.cgroup.devices.allow = c 5:0 rwm
### /dev/console
lxc.cgroup.devices.allow = c 5:1 rwm
### /dev/ptmx
lxc.cgroup.devices.allow = c 5:2 rwm
### fuse
lxc.cgroup.devices.allow = c 10:229 rwm
"
fi
cat <<-EOF >> "$config"
# Specify container architecture.
lxc.arch = $arch
# Set hostname.
lxc.uts.name = $hostname
# Include common configuration.
lxc.include = $LXC_TEMPLATE_CONFIG/sabayon.common.conf
$unprivileged_options
$privileged_options
EOF
}
#============================= Main ==============================#
parse_cmdline() {
# Parse command options.
local short_options="a:dm:n:p:r:hu"
local long_options="arch:,debug,mirror:,name:,path:,release:,rootfs:,mapped-uid:,mapped-gid:,flush-owner,help"
options=$(getopt -u -q -a -o "$short_options" -l "$long_options" -- "$@")
eval set -- "$options"
# Process command options.
while [ $# -gt 0 ]; do
case $1 in
-a | --arch)
arch=$2
shift
;;
-d | --debug)
debug='yes'
;;
-m | --mirror)
mirror_url=$2
shift
;;
-n | --name)
name=$2
shift
;;
-p | --path)
path=$2
shift
;;
-r | --release)
release=$2
shift
;;
--rootfs)
rootfs=$2
shift
;;
-u | --unprivileged)
unprivileged=true
;;
-h | --help)
usage
exit 1
;;
--mapped-uid)
mapped_uid=$2
shift
;;
--mapped-gid)
mapped_gid=$2
shift
;;
--flush-owner)
flush_owner=true
;;
--)
break
;;
*)
einfo "Unknown option: $1"
usage
exit 1
;;
esac
shift
done
if [ "$(id -u)" != "0" ]; then
die 1 "This script must be run as 'root'"
fi
# Validate options.
[ -n "$name" ] || die 1 'Missing required option --name'
[ -n "$path" ] || die 1 'Missing required option --path'
if [ -z "$rootfs" ] && [ -f "$path/config" ]; then
rootfs="$(sed -nE 's/^lxc.rootfs\s*=\s*(.*)$/\1/p' "$path/config")"
fi
if [ -z "$rootfs" ]; then
rootfs="$path/rootfs"
fi
[ -z "$path" ] && die 1 "'path' parameter is required."
arch=$(parse_arch "$arch") \
|| die 1 "Unsupported architecture: $arch"
[[ $unprivileged == true && $flush_owner == true &&-z "$mapped_uid" ]] && \
die 1 'Missing required option --mapped-uid with --unprivileged option'
[[ $unprivileged == true && $flush_owner == true && -z "$mapped_gid" ]] && \
die 1 'Missing required option --mapped-gid with --unprivileged option'
[[ $flush_owner == true && $unprivileged == false ]] && \
die 1 'flush-owner require --unprivileged option'
return 0
}
main () {
local tarball=""
# Set global variables.
RELEASE="${RELEASE:-"DAILY"}"
ARCH="${ARCH:-`uname -m`}"
OS="${OS:-"sabayon"}"
einfo "Processing command line arguments: $@"
# Parse command line options
parse_cmdline "$@"
DEBUG="$debug"
MIRROR_URL="${mirror_url:-$(random_mirror_url)}"
einfo "Use arch = $arch, mirror_url = $MIRROR_URL, path = $path, name = $name, release = $release, unprivileged = $unprivileged, rootfs = $rootfs, mapped_uid = $mapped_uid, mapped_gid = $mapped_gid, flush_owner = $flush_owner"
[ "$debug" = 'yes' ] && set -x
# Download sabayon tarball
tarball=$(create_url)
einfo "Fetching tarball $tarball..."
# TODO: use only a compression mode
if [ $arch == 'amd64' ] ; then
fetch "${tarball}" | tar -xpz -C "${rootfs}"
else
if [ $arch == 'armv7l' ] ; then
fetch "${tarball}" | tar -xpj -C "${rootfs}"
fi
fi
einfo "Tarball ${tarball} Extracted."
systemd_container_tuning
# Fix container for unprivileged mode.
if [[ $unprivileged == true ]] ; then
unprivileged_rootfs
if [[ $flush_owner == true ]] ; then
unprivileged_shift_owner
fi
fi
return 0
}
einfo "Prepare creation of sabayon container with params: $@ ($#)"
# Here we go!
run_exclusively 'main' 10 main "$@"
configure_container "$path/config" "$name" "$arch"
einfo "Container's rootfs and config have been created"
cat <<-EOF
Edit the config file $path/config to check/enable networking setup.
The installed system is preconfigured for a loopback and single network
interface configured via DHCP.
To start the container, run "lxc-start -n $name".
The root password is not set; to enter the container run "lxc-attach -n $name".
Note: From kenel >= 4.6 for use unprivileged containers it is needed this mount on host:
mkdir /sys/fs/cgroup/systemd
mount -t cgroup -o none,name=systemd systemd /sys/fs/cgroup/systemd
EOF

793
templates/lxc-slackware.in Normal file
View File

@ -0,0 +1,793 @@
#!/bin/bash
#
# lxc: linux Container library
# Authors:
# Daniel Lezcano <daniel.lezcano@free.fr>
# Template for slackware by Matteo Bernardini <ponce@slackbuilds.org>
# some parts are taken from the debian one (used as model)
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Detect use under userns (unsupported)
for arg in "$@"; do
[ "$arg" = "--" ] && break
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
echo "This template can't be used for unprivileged containers." 1>&2
echo "You may want to try the \"download\" template instead." 1>&2
exit 1
fi
done
# Add some directories to PATH in case we create containers with sudo
export PATH=/sbin:/usr/sbin:$PATH
cache=${cache:-/var/cache/lxc/slackware}
# Use the primary Slackware site by default, but please consider changing
# this to a closer mirror site.
MIRROR=${MIRROR:-http://ftp.slackware.com/pub/slackware}
if [ -z "$arch" ]; then
case "$( uname -m )" in
i?86) arch=i486 ;;
arm*) arch=arm ;;
*) arch=$( uname -m ) ;;
esac
fi
LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
configure_slackware()
{
rootfs=$1
hostname=$2
echo "Configuring..." ; echo
# The next part contains excerpts taken from SeTconfig (written by
# Patrick Volkerding) from the slackware setup disk.
# But before pasting them just set a variable to use them as they are
T_PX=$rootfs
( cd $T_PX ; chmod 755 ./ )
( cd $T_PX ; chmod 755 ./var )
if [ -d $T_PX/usr/src/linux ]; then
chmod 755 $T_PX/usr/src/linux
fi
if [ ! -d $T_PX/proc ]; then
mkdir $T_PX/proc
chown root.root $T_PX/proc
fi
if [ ! -d $T_PX/sys ]; then
mkdir $T_PX/sys
chown root.root $T_PX/sys
fi
chmod 1777 $T_PX/tmp
if [ ! -d $T_PX/var/spool/mail ]; then
mkdir -p $T_PX/var/spool/mail
chmod 755 $T_PX/var/spool
chown root.mail $T_PX/var/spool/mail
chmod 1777 $T_PX/var/spool/mail
fi
echo "#!/bin/sh" > $T_PX/etc/rc.d/rc.keymap
echo "# Load the keyboard map. More maps are in /usr/share/kbd/keymaps." \
>> $T_PX/etc/rc.d/rc.keymap
echo "if [ -x /usr/bin/loadkeys ]; then" >> $T_PX/etc/rc.d/rc.keymap
echo " /usr/bin/loadkeys us" >> $T_PX/etc/rc.d/rc.keymap
echo "fi" >> $T_PX/etc/rc.d/rc.keymap
chmod 755 $T_PX/etc/rc.d/rc.keymap
# Network configuration is left to the user, that have to edit
# /etc/rc.d/rc.inet1.conf and /etc/resolv.conf of the container
# just set the hostname
cat <<EOF > $rootfs/etc/HOSTNAME
$hostname.example.net
EOF
cp $rootfs/etc/HOSTNAME $rootfs/etc/hostname
# make needed devices, from Chris Willing's MAKEDEV.sh
# http://www.vislab.uq.edu.au/howto/lxc/MAKEDEV.sh
DEV=$rootfs/dev
mkdir -p ${DEV}
mknod -m 666 ${DEV}/null c 1 3
mknod -m 666 ${DEV}/zero c 1 5
mknod -m 666 ${DEV}/random c 1 8
mknod -m 666 ${DEV}/urandom c 1 9
mkdir -m 755 ${DEV}/pts
mkdir -m 1777 ${DEV}/shm
mknod -m 666 ${DEV}/tty c 5 0
mknod -m 600 ${DEV}/console c 5 1
mknod -m 666 ${DEV}/tty0 c 4 0
mknod -m 666 ${DEV}/tty1 c 4 1
mknod -m 666 ${DEV}/tty2 c 4 2
mknod -m 666 ${DEV}/tty3 c 4 3
mknod -m 666 ${DEV}/tty4 c 4 4
mknod -m 666 ${DEV}/tty5 c 4 5
mknod -m 666 ${DEV}/full c 1 7
mknod -m 600 ${DEV}/initctl p
mknod -m 660 ${DEV}/loop0 b 7 0
mknod -m 660 ${DEV}/loop1 b 7 1
ln -s pts/ptmx ${DEV}/ptmx
ln -s /proc/self/fd ${DEV}/fd
echo "Adding an etc/fstab"
cat >$rootfs/etc/fstab <<EOF
none /run tmpfs defaults,mode=0755 0 0
EOF
# simplify rc.6 and rc.S, http://www.vislab.uq.edu.au/howto/lxc/create_container.html
# and some other small fixes for a clean boot
cat >$rootfs/tmp/rcs.patch <<'EOF'
--- ./etc/rc.orig/rc.6 2012-08-15 01:03:12.000000000 +0200
+++ ./etc/rc.d/rc.6 2013-02-17 10:26:30.888839354 +0100
@@ -9,6 +9,12 @@
# Author: Miquel van Smoorenburg <miquels@drinkel.nl.mugnet.org>
# Modified by: Patrick J. Volkerding, <volkerdi@slackware.com>
#
+# minor tweaks for an lxc container
+# by Matteo Bernardini <ponce@slackbuilds.org>,
+# based also on Chris Willing's modifications
+# http://www.vislab.uq.edu.au/howto/lxc/rc.6
+# a check for a container variable is made to jump sections
+container="lxc"
# Set the path.
PATH=/sbin:/etc:/bin:/usr/bin
@@ -37,6 +43,9 @@
;;
esac
+# lxc container check
+if [ ! $container = "lxc" ]; then
+
# Save the system time to the hardware clock using hwclock --systohc.
if [ -x /sbin/hwclock ]; then
# Check for a broken motherboard RTC clock (where ioports for rtc are
@@ -53,6 +62,8 @@
fi
fi
+fi # end container check
+
# Run any local shutdown scripts:
if [ -x /etc/rc.d/rc.local_shutdown ]; then
/etc/rc.d/rc.local_shutdown stop
@@ -148,6 +159,9 @@
sleep 2
fi
+# lxc container check
+if [ ! $container = "lxc" ]; then
+
# Shut down PCMCIA devices:
if [ -x /etc/rc.d/rc.pcmcia ]; then
. /etc/rc.d/rc.pcmcia stop
@@ -155,11 +169,16 @@
/bin/sleep 5
fi
+fi # end container check
+
# Turn off process accounting:
if [ -x /sbin/accton -a -r /var/log/pacct ]; then
/sbin/accton off
fi
+# lxc container check
+if [ ! $container = "lxc" ]; then
+
# Terminate acpid before syslog:
if [ -x /etc/rc.d/rc.acpid -a -r /var/run/acpid.pid ]; then # quit
. /etc/rc.d/rc.acpid stop
@@ -170,6 +189,8 @@
sh /etc/rc.d/rc.udev force-stop
fi
+fi # end container check
+
# Kill all remaining processes.
if [ ! "$1" = "fast" ]; then
echo "Sending all processes the SIGTERM signal."
@@ -179,6 +200,9 @@
/sbin/killall5 -9
fi
+# lxc container check
+if [ ! $container = "lxc" ]; then
+
# Try to turn off quota.
if /bin/grep -q quota /etc/fstab ; then
if [ -x /sbin/quotaoff ]; then
@@ -187,6 +211,8 @@
fi
fi
+fi # end container check
+
# Carry a random seed between reboots.
echo "Saving random seed from /dev/urandom in /etc/random-seed."
# Use the pool size from /proc, or 512 bytes:
@@ -205,6 +231,9 @@
rm -f /var/lock/subsys/*
fi
+# lxc container check
+if [ ! $container = "lxc" ]; then
+
# Turn off swap:
echo "Turning off swap."
/sbin/swapoff -a
@@ -216,6 +245,8 @@
echo "Remounting root filesystem read-only."
/bin/mount -v -n -o remount,ro /
+fi # end container check
+
# This never hurts:
/bin/sync
@@ -240,12 +271,17 @@
done
fi
+# lxc container check
+if [ ! $container = "lxc" ]; then
+
# Deactivate LVM volume groups:
if [ -r /etc/lvmtab -o -d /etc/lvm/backup ]; then
echo "Deactivating LVM volume groups:"
/sbin/vgchange -an --ignorelockingfailure
fi
+fi # end container check
+
# This never hurts again (especially since root-on-LVM always fails
# to deactivate the / logical volume... but at least it was
# remounted as read-only first)
@@ -258,6 +294,9 @@
# This is to ensure all processes have completed on SMP machines:
wait
+# lxc container check
+if [ ! $container = "lxc" ]; then
+
if [ -x /sbin/genpowerd ]; then
# See if this is a powerfail situation:
if /bin/egrep -q "FAIL|SCRAM" /etc/upsstatus 2> /dev/null ; then
@@ -274,6 +313,13 @@
fi
fi
+else
+
+# confirm successful shutdown of the container
+echo ; echo "* container stopped. *" ; echo
+
+fi # end container check
+
# Now halt (poweroff with APM or ACPI enabled kernels) or reboot.
if [ "$command" = "reboot" ]; then
echo "Rebooting."
--- ./etc/rc.orig/rc.S 2012-09-13 21:38:34.000000000 +0200
+++ ./etc/rc.d/rc.S 2013-02-17 09:39:41.579799641 +0100
@@ -4,9 +4,18 @@
#
# Mostly written by: Patrick J. Volkerding, <volkerdi@slackware.com>
#
+# minor tweaks for an lxc container
+# by Matteo Bernardini <ponce@slackbuilds.org>,
+# based also on Chris Willing's modifications
+# http://www.vislab.uq.edu.au/howto/lxc/rc.S
+# a check for a container variable is made to jump sections
+container="lxc"
PATH=/sbin:/usr/sbin:/bin:/usr/bin
+# lxc container check
+if [ ! $container = "lxc" ]; then
+
# Try to mount /proc:
/sbin/mount -v proc /proc -n -t proc 2> /dev/null
@@ -254,10 +263,27 @@
read junk;
fi # Done checking root filesystem
+else
+ # We really don't want to start udev in the container
+ if [ -f /etc/rc.d/rc.udev ]; then
+ chmod -x /etc/rc.d/rc.udev
+ fi
+ # Alsa won't work
+ if [ -f /etc/rc.d/rc.alsa ]; then
+ chmod -x /etc/rc.d/rc.alsa
+ fi
+ # This too
+ if [ -f /etc/rc.d/rc.loop ]; then
+ chmod -x /etc/rc.d/rc.loop
+ fi
+fi # end container check
# Any /etc/mtab that exists here is old, so we start with a new one:
/bin/rm -f /etc/mtab{,~,.tmp} && /bin/touch /etc/mtab
+# lxc container check
+if [ ! $container = "lxc" ]; then
+
# Add entry for / to /etc/mtab:
/sbin/mount -f -w /
@@ -337,6 +363,8 @@
# mounted read-write.
/sbin/swapon -a 2> /dev/null
+fi # end container check
+
# Clean up some temporary files:
rm -f /var/run/* /var/run/*/* /var/run/*/*/* /etc/nologin \
/etc/dhcpc/*.pid /etc/forcefsck /etc/fastboot \
@@ -364,7 +392,7 @@
# if the first line of that file begins with the word 'Linux'.
# You are free to modify the rest of the file as you see fit.
if [ -x /bin/sed ]; then
- /bin/sed -i "{1s/^Linux.*/$(/bin/uname -sr)\./}" /etc/motd
+ /bin/sed -i "{1s/^Linux.*/$(/bin/uname -sr) lxc container\./}" /etc/motd
fi
# If there are SystemV init scripts for this runlevel, run them.
@@ -372,6 +400,9 @@
. /etc/rc.d/rc.sysvinit
fi
+# lxc container check
+if [ ! $container = "lxc" ]; then
+
# Run serial port setup script:
# CAREFUL! This can make some systems hang if the rc.serial script isn't
# set up correctly. If this happens, you may have to edit the file from a
@@ -380,6 +411,8 @@
sh /etc/rc.d/rc.serial start
fi
+fi # end container check
+
# Carry an entropy pool between reboots to improve randomness.
if [ -f /etc/random-seed ]; then
echo "Using /etc/random-seed to initialize /dev/urandom."
--- ./etc/rc.orig/rc.M 2012-09-25 19:47:07.000000000 +0200
+++ ./etc/rc.d/rc.M 2013-02-17 09:39:41.579799641 +0100
@@ -10,6 +10,10 @@
# Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
# Heavily modified by Patrick Volkerding <volkerdi@slackware.com>
#
+# minor tweaks for an lxc container
+# by Matteo Bernardini <ponce@slackbuilds.org>:
+# a check for a container variable is made to jump sections
+container="lxc"
# Tell the viewers what's going to happen.
echo "Going multiuser..."
@@ -20,6 +24,9 @@
/sbin/ldconfig &
fi
+# lxc container check
+if [ ! $container = "lxc" ]; then
+
# Screen blanks after 15 minutes idle time, and powers down in one hour
# if the kernel supports APM or ACPI power management:
/bin/setterm -blank 15 -powersave powerdown -powerdown 60
@@ -33,6 +40,8 @@
/bin/hostname darkstar
fi
+fi # end container check
+
# Set the permissions on /var/log/dmesg according to whether the kernel
# permits non-root users to access kernel dmesg information:
if [ -r /proc/sys/kernel/dmesg_restrict ]; then
@@ -135,6 +144,9 @@
chmod 755 / 2> /dev/null
chmod 1777 /tmp /var/tmp
+# lxc container check
+if [ ! $container = "lxc" ]; then
+
# Start APM or ACPI daemon.
# If APM is enabled in the kernel, start apmd:
if [ -e /proc/apm ]; then
@@ -146,6 +158,8 @@
. /etc/rc.d/rc.acpid start
fi
+fi # end container check
+
# Update any existing icon cache files:
if find /usr/share/icons 2> /dev/null | grep -q icon-theme.cache ; then
for theme_dir in /usr/share/icons/* ; do
--- ./etc/rc.orig/rc.inet1 2012-08-05 19:13:27.000000000 +0200
+++ ./etc/rc.d/rc.inet1 2013-02-17 09:39:41.579799641 +0100
@@ -3,6 +3,11 @@
# This script is used to bring up the various network interfaces.
#
# @(#)/etc/rc.d/rc.inet1 10.2 Sun Jul 24 12:45:56 PDT 2005 (pjv)
+#
+# minor tweaks for an lxc container
+# by Matteo Bernardini <ponce@slackbuilds.org>:
+# a check for a container variable is made to jump sections
+container="lxc"
############################
# READ NETWORK CONFIG FILE #
@@ -105,6 +110,10 @@
[ "${IFNAME[$i]}" = "${1}" ] && break
i=$(($i+1))
done
+
+ # lxc container check
+ if [ ! $container = "lxc" ]; then
+
# If the interface is a bridge, then create it first:
[ -n "${BRNICS[$i]}" ] && br_open $i
# If the interface isn't in the kernel yet (but there's an alias for it in
@@ -115,6 +124,9 @@
/sbin/modprobe ${1}
fi
fi
+
+ fi # end container check
+
if grep `echo ${1}: | cut -f 1 -d :`: /proc/net/dev 1> /dev/null ; then # interface exists
if ! /sbin/ifconfig | grep -w "${1}" 1>/dev/null || \
! /sbin/ifconfig ${1} | grep -w inet 1> /dev/null ; then # interface not up or not configured
EOF
( cd $rootfs ; patch -p1 < tmp/rcs.patch ; rm tmp/rcs.patch )
# restart rc.inet1 to have routing for the loop device
echo "/etc/rc.d/rc.inet1 restart" >> $rootfs/etc/rc.d/rc.local
# reduce the number of local consoles: two should be enough
sed -i '/^c3\|^c4\|^c5\|^c6/s/^/# /' $rootfs/etc/inittab
# better not use this in a container
sed -i 's/.*genpowerfail.*//' $rootfs/etc/inittab
# add a message to rc.local that confirms successful container startup
echo "echo ; echo \"* container $name started. *\" ; echo" >> $rootfs/etc/rc.d/rc.local
# borrow the time configuration from the local machine
cp -a /etc/localtime $rootfs/etc/localtime
return 0
}
copy_slackware()
{
rootfs=$1
# make a local copy of the installed filesystem
echo -n "Copying rootfs to $rootfs..."
mkdir -p $rootfs
cp -a $cache/rootfs-$release-$arch/* $rootfs/ || exit 1
# fix fstab with the actual path
sed -i "s|$cache/rootfs-$release-$arch|$rootfs|" $rootfs/etc/fstab
return 0
}
install_slackware()
{
rootfs=$1
mkdir -p /var/lock/subsys/
(
flock -n -x 9
if [ $? -ne 0 ]; then
echo "Cache repository is busy."
return 1
fi
if [ "$arch" == "x86_64" ]; then
PKGMAIN=slackware64
elif [ "$arch" == "arm" ]; then
PKGMAIN=slackwarearm
else
PKGMAIN=slackware
fi
export CONF=$cache/slackpkg-conf
export ROOT=$cache/rootfs-$release-$arch
mkdir -p $cache/cache-$release-$arch $cache/rootfs-$release-$arch \
$cache/slackpkg-$release-$arch $CONF/templates
echo "$MIRROR/$PKGMAIN-$release/" > $CONF/mirrors
touch $CONF/blacklist
cat <<EOF > $CONF/slackpkg.conf
# v2.8
ARCH=$arch
TEMP=$cache/cache-$release-$arch
WORKDIR=$cache/slackpkg-$release-$arch
DELALL=off
CHECKMD5=on
CHECKGPG=on
CHECKSIZE=off
PRIORITY=( patches %PKGMAIN extra pasture testing )
POSTINST=on
ONLY_NEW_DOTNEW=off
ONOFF=on
DOWNLOAD_ALL=on
DIALOG=off
BATCH=on
DEFAULT_ANSWER=y
USE_INCLUDES=on
SPINNING=off
EOF
# thanks to Vincent Batts for this list of packages
# (that I modified a little :P)
# http://connie.slackware.com/~vbatts/minimal/
cat <<EOF > $CONF/templates/minimal-lxc.template
aaa_base
aaa_elflibs
aaa_terminfo
bash
bin
bzip2
coreutils
dhcpcd
dialog
diffutils
e2fsprogs
elvis
etc
findutils
gawk
glibc-solibs
gnupg
grep
gzip
hostname
iputils
libunistring
logrotate
mpfr
net-tools
network-scripts
ncurses
openssh
openssl-solibs
pkgtools
procps-ng
sed
shadow
sharutils
slackpkg
sysklogd
sysvinit
sysvinit-functions
sysvinit-scripts
tar
udev
util-linux
wget
which
xz
EOF
TEMPLATE=${TEMPLATE:-minimal-lxc}
if [ ! "$TEMPLATE" = "minimal-lxc" ]; then
if [ -f /etc/slackpkg/templates/$TEMPLATE.template ]; then
cat /etc/slackpkg/templates/$TEMPLATE.template \
> $CONF/templates/$TEMPLATE.template
else
TEMPLATE="minimal-lxc"
fi
fi
# clean previous installs
rm -fR $ROOT/*
slackpkg -default_answer=n update
slackpkg install-template $TEMPLATE
# add a slackpkg default mirror
echo "$MIRROR/$PKGMAIN-$release/" >> $ROOT/etc/slackpkg/mirrors
# blacklist the devs package (we have to use our premade devices).
# do the same with the kernel packages (we use the host's one),
# but leave available headers and sources
echo "devs" >> $ROOT/etc/slackpkg/blacklist
sed -i \
-e "s|^#kernel-|kernel-|" \
-e "s|^kernel-headers|#kernel-headers|" \
-e "s|^kernel-source|#kernel-source|" \
$ROOT/etc/slackpkg/blacklist
# force klog to use the system call interface to the kernel message
# buffers - needed for unprivileged containers
sed -i 's|3\ \-x|3 -x -s|' $ROOT/etc/rc.d/rc.syslog || true
return 0
) 9>/var/lock/subsys/lxc
return $?
}
copy_configuration()
{
path=$1
rootfs=$2
name=$3
cat <<EOF >> $path/config
lxc.uts.name = $name
lxc.arch = $arch
lxc.mount.fstab = $rootfs/etc/fstab
lxc.include = ${LXC_TEMPLATE_CONFIG}/slackware.common.conf
EOF
if [ $? -ne 0 ]; then
echo "Failed to add configuration."
return 1
fi
return 0
}
clean()
{
if [ ! -e $cache ]; then
exit 0
fi
# lock, so we won't purge while someone is creating a repository
(
flock -n -x 9
if [ $? != 0 ]; then
echo "Cache repository is busy."
exit 1
fi
echo -n "Purging the download cache..."
rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
exit 0
) 9>/var/lock/subsys/lxc
}
usage()
{
cat <<EOF
$1 -h|--help -p|--path=<path> --clean
EOF
return 0
}
options=$(getopt -o hp:n:a:r:c -l help,rootfs:,path:,name:,arch:,release:,clean -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
fi
eval set -- "$options"
while true
do
case "$1" in
-h|--help) usage $0 && exit 0;;
-p|--path) path=$2; shift 2;;
--rootfs) rootfs=$2; shift 2;;
-a|--arch) arch=$2; shift 2;;
-r|--release) release=$2; shift 2;;
-n|--name) name=$2; shift 2;;
-c|--clean) clean=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
if [ ! -z "$clean" -a -z "$path" ]; then
clean || exit 1
exit 0
fi
type installpkg
if [ $? -ne 0 ]; then
echo "'installpkg' command is missing."
exit 1
fi
type slackpkg
if [ $? -ne 0 ]; then
echo "'slackpkg' command is missing."
exit 1
fi
if [ -z "$path" ]; then
echo "'path' parameter is required."
exit 1
fi
if [ "$(id -u)" != "0" ]; then
echo "This script should be run as 'root'."
exit 1
fi
# If no release version was specified, use current
release=${release:-current}
if [ -z "$name" ]; then
# no name given? set a default one
name=slackwarecontainer
fi
# detect rootfs
config="$path/config"
if [ -z "$rootfs" ]; then
if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then
rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config)
else
rootfs=$path/rootfs
fi
fi
echo
set -e
install_slackware $rootfs
if [ $? -ne 0 ]; then
echo "Failed to install slackware."
exit 1
fi
echo
configure_slackware $cache/rootfs-$release-$arch $name
if [ $? -ne 0 ]; then
echo "Failed to configure slackware for a container."
exit 1
fi
echo
rootfs=$path/rootfs
copy_slackware $rootfs
if [ $? -ne 0 ]; then
echo "Failed to copy rootfs."
exit 1
fi
echo
copy_configuration $path $rootfs $name
if [ $? -ne 0 ]; then
echo "Failed to write configuration file."
exit 1
fi
if [ ! -z $clean ]; then
clean || exit 1
exit 0
fi

702
templates/lxc-sparclinux.in Normal file
View File

@ -0,0 +1,702 @@
#!/bin/sh
#
# Template script for generating Linux for SPARC for LXC
# based on lxc-fedora, lxc-ubuntu
#
# Copyright © 2011 Wim Coekaerts <wim.coekaerts@oracle.com>
# Copyright © 2012 Dwight Engen <dwight.engen@oracle.com>
# Copyright <20> 2015 Wim Coekaerts <wim.coekaerts@oracle.com>
#
# Modified for Oracle Linux 5
# Wim Coekaerts <wim.coekaerts@oracle.com>
#
# Modified for Oracle Linux 6,7 combined OL4,5,6 into one template script
# Dwight Engen <dwight.engen@oracle.com>
#
# Modified for Linux for SPARC 1.0
# Wim Coekaerts <wim.coekaerts@oracle.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
# Detect use under userns (unsupported)
for arg in "$@"; do
[ "$arg" = "--" ] && break
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
echo "This template can't be used for unprivileged containers." 1>&2
echo "You may want to try the \"download\" template instead." 1>&2
exit 1
fi
done
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
die()
{
echo "failed: $1"
exit 1
}
is_btrfs_subvolume()
{
if which btrfs >/dev/null 2>&1 && \
btrfs subvolume list "$1" >/dev/null 2>&1; then
return 0
fi
return 1
}
can_chcon()
{
if which chcon >/dev/null 2>&1; then
selinuxenabled >/dev/null 2>&1
return $?
fi
return 1
}
# fix up the container_rootfs
container_rootfs_patch()
{
echo "Patching container rootfs $container_rootfs for Linux for SPARC $container_release_major.$container_release_minor"
# copy ourself into the container to be used to --patch the rootfs when
# yum update on certain packages is done. we do this here instead of in
# container_rootfs_configure() in case the patching done in this function
# is updated in the future, we can inject the updated version of ourself
# into older containers.
if [ $container_rootfs != "/" ]; then
cp -f `readlink -f $0` $container_rootfs/usr/bin/lxc-patch
mkdir -p $container_rootfs/usr/share/yum-plugins
cp @DATADIR@/lxc/lxc-patch.py $container_rootfs/usr/share/yum-plugins
mkdir -p $container_rootfs/etc/yum/pluginconf.d
cat <<EOF > $container_rootfs/etc/yum/pluginconf.d/lxc-patch.conf
[main]
enabled=1
packages=dbus,initscripts,iptables,openssh-server,setup,selinux-policy,readahead,udev,util-linux,util-linux-ng
EOF
fi
# "disable" selinux in the guest. The policy in the container isn't
# likely to match the hosts (unless host == guest exactly) and the
# kernel can only be enforcing one policy.
#
mkdir -p $container_rootfs/selinux
echo 0 > $container_rootfs/selinux/enforce
if [ -e $container_rootfs/etc/selinux/config ]; then
sed -i 's|SELINUX=enforcing|SELINUX=disabled|' $container_rootfs/etc/selinux/config
else
mkdir -p $container_rootfs/etc/selinux
echo "SELINUX=disabled" >$container_rootfs/etc/selinux/config
fi
sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*close|#session required pam_selinux.so close|' $container_rootfs/etc/pam.d/login
sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*open|#session required pam_selinux.so open|' $container_rootfs/etc/pam.d/login
sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*close|#session required pam_selinux.so close|' $container_rootfs/etc/pam.d/sshd
sed -i 's|session[ \t]*required[ \t]*pam_selinux.so[ \t]*open|#session required pam_selinux.so open|' $container_rootfs/etc/pam.d/sshd
# setting /proc/$$/loginuid doesn't work under user namespace, which
# prevents logins from working
sed -i 's|session[ \t]*required[ \t]*pam_loginuid.so|#session required pam_loginuid.so|' $container_rootfs/etc/pam.d/sshd
sed -i 's|session[ \t]*required[ \t]*pam_loginuid.so|#session required pam_loginuid.so|' $container_rootfs/etc/pam.d/login
if [ -f $container_rootfs/usr/sbin/selinuxenabled ]; then
mv $container_rootfs/usr/sbin/selinuxenabled $container_rootfs/usr/sbin/selinuxenabled.lxcorig
ln -s /bin/false $container_rootfs/usr/sbin/selinuxenabled
fi
# ensure /dev/ptmx refers to the newinstance devpts of the container, or
# pty's will get crossed up with the hosts (https://lkml.org/lkml/2012/1/23/512)
rm -f $container_rootfs/dev/ptmx
ln -s pts/ptmx $container_rootfs/dev/ptmx
# silence error in checking for selinux
sed -i 's|cat /proc/self/attr/current|cat /proc/self/attr/current 2>/dev/null|' $container_rootfs/etc/rc.sysinit
sed -i 's|cat /proc/self/attr/current|cat /proc/self/attr/current 2>/dev/null|' $container_rootfs/etc/rc.d/rc.sysinit
# disable ipv6
rm -f $container_rootfs/etc/sysconfig/network-scripts/init.ipv6-global
# remove module stuff for iptables it just shows errors that are not
# relevant in a container
if [ -f "$container_rootfs/etc/sysconfig/iptables-config" ]; then
sed -i 's|IPTABLES_MODULES=".*|IPTABLES_MODULES=""|' $container_rootfs/etc/sysconfig/iptables-config
sed -i 's|IPTABLES_MODULES_UNLOAD=".*|IPTABLES_MODULES_UNLOAD="no"|' $container_rootfs/etc/sysconfig/iptables-config
fi
# disable readahead in the container
if [ $container_release_major = "1" -a -e $container_rootfs/etc/sysconfig/readahead ]; then
rm -f $container_rootfs/etc/init/readahead-collector.conf
rm -f $container_rootfs/etc/init/readahead-disable-services.conf
sed -i 's|READAHEAD="yes"|READAHEAD="no"|' $container_rootfs/etc/sysconfig/readahead
fi
# no need to attempt to mount /
sed -i 's|mount -f /$|# LXC mount -f /|' $container_rootfs/etc/rc.sysinit
sed -i 's|mount -f /$|# LXC mount -f /|' $container_rootfs/etc/rc.d/rc.sysinit
sed -i 's|action \$"Remounting root filesystem|/bin/true # LXC action $"Remounting root filesystem|' $container_rootfs/etc/rc.sysinit
sed -i 's|action \$"Remounting root filesystem|/bin/true # LXC action $"Remounting root filesystem|' $container_rootfs/etc/rc.d/rc.sysinit
# disable udev in the container
sed -i 's|.sbin.start_udev||' $container_rootfs/etc/rc.sysinit
sed -i 's|.sbin.start_udev||' $container_rootfs/etc/rc.d/rc.sysinit
sed -i 's|\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.d/init.d/halt
sed -i 's|^\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.sysinit
sed -i 's|^\[ -x /sbin/hwclock|\[ 0 -eq 1|' $container_rootfs/etc/rc.d/rc.sysinit
sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.sysinit
sed -i 's|^/sbin/hwclock|# LXC /sbin/nohwclock|' $container_rootfs/etc/rc.d/rc.sysinit
touch $container_rootfs/.nolvm
# fix assumptions that plymouth is available
sed -i 's|\[ "$PROMPT" != no \] && plymouth|[ "$PROMPT" != no ] \&\& [ -n "$PLYMOUTH" ] \&\& plymouth|' $container_rootfs/etc/rc.sysinit
sed -i 's|\[ "$PROMPT" != no \] && plymouth|[ "$PROMPT" != no ] \&\& [ -n "$PLYMOUTH" ] \&\& plymouth|' $container_rootfs/etc/rc.d/rc.sysinit
rm -f $container_rootfs/etc/init/plymouth-shutdown.conf
rm -f $container_rootfs/etc/init/quit-plymouth.conf
rm -f $container_rootfs/etc/init/splash-manager.conf
# dont try to unmount /dev/lxc devices
sed -i 's|&& $1 !~ /^\\/dev\\/ram/|\&\& $2 !~ /^\\/dev\\/lxc/ \&\& $1 !~ /^\\/dev\\/ram/|' $container_rootfs/etc/init.d/halt
# don't try to unmount swap
sed -i 's|\[ -f /proc/swaps \]|# LXC [ -f /proc/swaps ]|' $container_rootfs/etc/init.d/halt
sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.sysinit
sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.d/rc.sysinit
# there might be other services that are useless but the below set is a good start
# some of these might not exist in the image, so we silence chkconfig complaining
# about the service file not being found
for service in \
acpid apmd auditd autofs cpuspeed dund gpm haldaemon hidd \
ip6tables irqbalance iscsi iscsid isdn kdump kudzu \
lm_sensors lvm2-monitor mdmonitor microcode_ctl \
ntpd pcmcia postfix sendmail udev-post xfs ;
do
chroot $container_rootfs chkconfig 2>/dev/null $service off
done
for service in rsyslog ;
do
chroot $container_rootfs chkconfig 2>/dev/null $service on
done
}
container_rootfs_configure()
{
container_rootfs_patch
echo "Configuring container for Linux for SPARC $container_release_major.$container_release_minor"
# configure the network to use dhcp. we set DHCP_HOSTNAME so the guest
# will report its name and be resolv'able by the hosts dnsmasq
cat <<EOF > $container_rootfs/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
HOSTNAME=$name
DHCP_HOSTNAME=\`hostname\`
NM_CONTROLLED=no
TYPE=Ethernet
EOF
cat <<EOF > $container_rootfs/etc/sysconfig/network
NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=$name
EOF
# set minimal hosts
echo "127.0.0.1 localhost $name" > $container_rootfs/etc/hosts
# this file has to exist for libvirt/Virtual machine monitor to boot the container
touch $container_rootfs/etc/mtab
# setup console and tty[1-4] for login. note that /dev/console and
# /dev/tty[1-4] will be symlinks to the ptys /dev/lxc/console and
# /dev/lxc/tty[1-4] so that package updates can overwrite the symlinks.
# lxc will maintain these links and bind mount ptys over /dev/lxc/*
# since lxc.tty.dir is specified in the config.
# allow root login on console, tty[1-4], and pts/0 for libvirt
echo "# LXC (Linux Containers)" >>$container_rootfs/etc/securetty
echo "lxc/console" >>$container_rootfs/etc/securetty
for i in 1 2 3 4; do
echo "lxc/tty$i" >>$container_rootfs/etc/securetty
done
echo "# For libvirt/Virtual Machine Monitor" >>$container_rootfs/etc/securetty
for i in 0 1 2 3 4; do
echo "pts/$i" >>$container_rootfs/etc/securetty
done
# prevent mingetty from calling vhangup(2) since it fails with userns
if [ -f $container_rootfs/etc/init/tty.conf ]; then
sed -i 's|mingetty|mingetty --nohangup|' $container_rootfs/etc/init/tty.conf
fi
# create maygetty which only spawns a getty on the console when running
# under lxc, not libvirt-lxc which symlinks /dev/console to the same pty
# as /dev/tty1
cat <<EOF >$container_rootfs/sbin/maygetty
#!/bin/sh
if [ "\$container" = "lxc" ]; then
exec /sbin/mingetty \$@
fi
exec sleep infinity
EOF
chmod 755 $container_rootfs/sbin/maygetty
cat <<EOF > $container_rootfs/etc/init/console.conf
# console - getty
#
# This service maintains a getty on the console from the point the system is
# started until it is shut down again.
start on stopped rc RUNLEVEL=[2345]
stop on runlevel [!2345]
env container
respawn
exec /sbin/maygetty --nohangup --noclear /dev/console
EOF
cat <<EOF > $container_rootfs/etc/init/power-status-changed.conf
# power-status-changed - used to cleanly shut down the container
#
# This task is run whenever init receives SIGPWR
# Used to shut down the machine.
start on power-status-changed
exec init 0
EOF
# start with a clean /var/log/messages
rm -f $container_rootfs/var/log/messages
# set initial timezone as on host
if [ -f /etc/sysconfig/clock ]; then
. /etc/sysconfig/clock
echo ZONE=$ZONE > $container_rootfs/etc/sysconfig/clock
chroot $container_rootfs tzdata-update
else
echo "Timezone in container is not configured. Adjust it manually."
fi
# add oracle user
chroot $container_rootfs useradd -m -s /bin/bash oracle
printf "Added container user:\033[1moracle\033[0m\n"
printf "Added container user:\033[1mroot\033[0m\n"
}
# create the container's lxc config file
container_config_create()
{
echo "Create configuration file $cfg_dir/config"
mkdir -p $cfg_dir || die "unable to create config dir $cfg_dir"
echo "# Common configuration" >> $cfg_dir/config
if [ -e "@LXCTEMPLATECONFIG@/sparclinux.common.conf" ]; then
echo "lxc.include = @LXCTEMPLATECONFIG@/sparclinux.common.conf" >> $cfg_dir/config
fi
cat <<EOF >> $cfg_dir/config || die "unable to create $cfg_dir/config"
# Container configuration for Linux for SPARC $container_release_major.$container_release_minor
lxc.arch = $arch
lxc.uts.name = $name
EOF
grep -q "^lxc.rootfs.path" $cfg_dir/config 2>/dev/null || echo "lxc.rootfs.path = $container_rootfs" >> $cfg_dir/config
echo "lxc.cap.drop = sys_resource" >>$cfg_dir/config
echo "lxc.cap.drop = setfcap setpcap" >>$cfg_dir/config
echo "# Networking" >>$cfg_dir/config
# see if the default network settings were already specified
lxc_network_type=`grep '^lxc.net.0.type' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
if [ -z "$lxc_network_type" ]; then
echo "lxc.net.0.type = veth" >>$cfg_dir/config
lxc_network_type=veth
fi
lxc_network_link=`grep '^lxc.net.0.link' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
if [ -z "$lxc_network_link" ]; then
echo "lxc.net.0.link = lxcbr0" >>$cfg_dir/config
lxc_network_link=lxcbr0
fi
lxc_network_hwaddr=`grep '^lxc.net.0.hwaddr' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
if [ -z "$lxc_network_hwaddr" ]; then
# generate a hwaddr for the container
# see http://sourceforge.net/tracker/?func=detail&aid=3411497&group_id=163076&atid=826303
local hwaddr="00:16:3e:`dd if=/dev/urandom bs=8 count=1 2>/dev/null |od -t x8 | \
head -n1 | awk '{print $2}' | cut -c1-6 | \
sed 's/\(..\)/\1:/g; s/.$//'`"
echo "lxc.net.0.hwaddr = $hwaddr" >>$cfg_dir/config
fi
lxc_network_flags=`grep '^lxc.net.0.flags' $cfg_dir/config | awk -F'[= \t]+' '{ print $2 }'`
if [ -z "$lxc_network_flags" ]; then
echo "lxc.net.0.flags = up" >>$cfg_dir/config
fi
cat <<EOF >> $cfg_dir/config || die "unable to create $cfg_dir/config"
lxc.net.0.name = eth0
lxc.net.0.mtu = 1500
EOF
}
container_rootfs_clone()
{
if is_btrfs_subvolume $template_rootfs; then
# lxc-create already made $container_rootfs a btrfs subvolume, but
# in this case we want to snapshot the original subvolume so we we
# have to delete the one that lxc-create made
btrfs subvolume delete $container_rootfs
btrfs subvolume snapshot $template_rootfs $container_rootfs || die "btrfs clone template"
else
echo "Copying rootfs ..."
cp -axT $template_rootfs $container_rootfs || die "copy template"
fi
}
container_rootfs_repo_create()
{
echo "# LXC generated .repo file" >$1
echo "[$2]" >>$1
echo "name=Linux for SPARC $container_release_major.$container_release_minor ($basearch)" >>$1
echo "baseurl=$3/" >>$1
echo "enabled=1" >>$1
echo "skip_if_unavailable=1" >>$1
if [ "$4" != "" ]; then
echo "gpgkey=$yum_url/RPM-GPG-KEY-oracle-ol$container_release_major" >>$1
echo "gpgcheck=1" >>$1
else
echo "gpgcheck=0" >>$1
fi
}
container_rootfs_dev_create()
{
# create required devices. note that /dev/console will be created by lxc
# or libvirt itself to be a symlink to the right pty.
# take care to not nuke /dev in case $container_rootfs isn't set
dev_path="$container_rootfs/dev"
if [ $container_rootfs != "/" -a -d $dev_path ]; then
rm -rf $dev_path
fi
mkdir -p $dev_path
if can_chcon; then
# ensure symlinks created in /dev have the right context
chcon -t device_t $dev_path
fi
mknod -m 666 $dev_path/null c 1 3
mknod -m 666 $dev_path/zero c 1 5
mknod -m 666 $dev_path/random c 1 8
mknod -m 666 $dev_path/urandom c 1 9
mkdir -m 755 $dev_path/pts
mkdir -m 1777 $dev_path/shm
mknod -m 666 $dev_path/tty c 5 0
mknod -m 666 $dev_path/tty1 c 4 1
mknod -m 666 $dev_path/tty2 c 4 2
mknod -m 666 $dev_path/tty3 c 4 3
mknod -m 666 $dev_path/tty4 c 4 4
mknod -m 666 $dev_path/full c 1 7
mknod -m 600 $dev_path/initctl p
# set selinux labels same as host
if can_chcon; then
for node in null zero random urandom pts shm \
tty tty0 tty1 tty2 tty3 tty4 full ;
do
chcon --reference /dev/$node $dev_path/$node 2>/dev/null
done
fi
}
container_rootfs_create()
{
if can_chcon; then
chcon --reference / $container_rootfs 2>/dev/null
fi
cmds="rpm wget yum"
for cmd in $cmds; do
which $cmd >/dev/null 2>&1
if [ $? -ne 0 ]; then
die "The $cmd command is required, please install it"
fi
done
mkdir -p @LOCALSTATEDIR@/lock/subsys
(
flock -x 9
if [ $? -ne 0 ]; then
die "The template is busy."
fi
echo "Yum installing release $container_release_major.$container_release_minor for $basearch"
if [ -n "$repourl" ]; then
yum_url=$repourl
else
yum_url=http://yum.oracle.com
fi
if [ -n "$baseurl" ]; then
# create .repo pointing at baseurl
repo="lxc-install"
mkdir -p $container_rootfs/etc/yum.repos.d
container_rootfs_repo_create \
$container_rootfs/etc/yum.repos.d/lxc-install.repo $repo $baseurl
else
# get public-yum repo file
if [ $container_release_major = "1" ]; then
repofile=yum-linux-sparc64.repo
else
die "Unsupported release $container_release_major"
fi
mkdir -p $container_rootfs/etc/yum.repos.d
wget -q $yum_url/$repofile -O $container_rootfs/etc/yum.repos.d/$repofile
if [ $? -ne 0 ]; then
die "Unable to download repo file $yum_url/$repofile, release unavailable"
fi
# yum will take $basearch from host, so force the arch we want
sed -i "s|\$basearch|$basearch|" $container_rootfs/etc/yum.repos.d/$repofile
# replace url if they specified one
if [ -n "$repourl" ]; then
sed -i "s|baseurl=http://yum.oracle.com/|baseurl=$repourl/repo|" $container_rootfs/etc/yum.repos.d/$repofile
sed -i "s|gpgkey=http://yum.oracle.com|gpgkey=$repourl|" $container_rootfs/etc/yum.repos.d/$repofile
fi
# disable all repos, then enable the repo for the version we are installing.
if [ $container_release_minor = "latest" ]; then
repo="lfs"_$container_release_minor
else
die "Unsupported release $container_release_major.$container_release_minor"
fi
sed -i "s|enabled=1|enabled=0|" $container_rootfs/etc/yum.repos.d/$repofile
sed -i "/\[$repo\]/,/\[/ s/enabled=0/enabled=1/" $container_rootfs/etc/yum.repos.d/$repofile
fi
container_rootfs_dev_create
# don't put devpts,proc, nor sysfs in here, it will already be mounted for us by lxc/libvirt
echo "" >$container_rootfs/etc/fstab
# create rpm db, download and yum install minimal packages
mkdir -p $container_rootfs/var/lib/rpm
rpm --root $container_rootfs --initdb
yum_args="--installroot $container_rootfs --disablerepo=* --enablerepo=$repo -y --nogpgcheck"
min_pkgs="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils sparclinux-release"
# we unshare the mount namespace because yum installing the ol4
# packages causes $rootfs/proc to be mounted on
lxc-unshare -s MOUNT yum -- $yum_args install $min_pkgs $user_pkgs
if [ $? -ne 0 ]; then
die "Failed to download and install the rootfs, aborting."
fi
# rsyslog and pam depend on coreutils for some common commands in
# their POSTIN scriptlets, but coreutils wasn't installed yet. now
# that coreutils is installed, reinstall the packages so their POSTIN
# runs right. similarly, libutempter depends on libselinux.so.1 when
# it runs /usr/sbin/groupadd, so reinstall it too
redo_pkgs=""
if [ x"$redo_pkgs" != x ]; then
rpm --root $container_rootfs --nodeps -e $redo_pkgs
lxc-unshare -s MOUNT yum -- $yum_args install $redo_pkgs
if [ $? -ne 0 ]; then
die "Unable to reinstall packages"
fi
fi
# these distributions put the rpm database in a place the guest is
# not expecting it, so move it
if [ $host_distribution = "Ubuntu" -o $host_distribution = "Debian" ]; then
mv $container_rootfs/$HOME/.rpmdb/* $container_rootfs/var/lib/rpm
fi
# if the native rpm created the db with Hash version 9, we need to
# downgrade it to Hash version 8 for use with OL5.x
db_version=`file $container_rootfs/var/lib/rpm/Packages | \
grep -o 'version [0-9]*' |awk '{print $2}'`
# the host rpm may not be the same as the guest, rebuild the db with
# the guest rpm version
echo "Rebuilding rpm database"
rm -f $container_rootfs/var/lib/rpm/__db*
chroot $container_rootfs rpm --rebuilddb >/dev/null 2>&1
) 9>@LOCALSTATEDIR@/lock/subsys/lxc-sparclinux-$name
if [ $? -ne 0 ]; then
exit 1
fi
}
container_release_get()
{
if [ -f $1/etc/sparclinux-release ]; then
container_release_version=`cat $1/etc/sparclinux-release |awk '/^Linux/ {print $5}'`
container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'`
container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'`
else
echo "Unable to determine container release version"
exit 1
fi
}
usage()
{
cat <<EOF
-a|--arch=<arch> architecture (sparc64)
-R|--release=<release> release to download for the new container
--rootfs=<path> rootfs path
-r|--rpms=<rpm name> additional rpms to install into container
-u|--url=<url> replace yum repo url (ie. Oracle public-yum mirror)
--baseurl=<url> use package repository (ie. file:///mnt)
arch and release must also be specified
-t|--templatefs=<path> copy/clone rootfs at path instead of downloading
-P|--patch=<path> only patch the rootfs at path for use as a container
-h|--help
Release is of the format "major.minor", for example "1.0" or "1.latest"
This template supports Linux for SPARC release 1.0
EOF
return 0
}
options=$(getopt -o hp:n:a:R:r:u:t: -l help,rootfs:,path:,name:,arch:,release:,rpms:,url:,templatefs:,patch:,baseurl: -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
fi
eval set -- "$options"
while true
do
case "$1" in
-h|--help) usage $0 && exit 0;;
-p|--path) cfg_dir=$2; shift 2;;
--rootfs) container_rootfs=$2; shift 2;;
-n|--name) name=$2; shift 2;;
-a|--arch) arch=$2; shift 2;;
-R|--release) container_release_version=$2; shift 2;;
-r|--rpms) user_pkgs=$2; shift 2;;
-u|--url) repourl=$2; shift 2;;
-t|--templatefs) template_rootfs=$2; shift 2;;
--patch) patch_rootfs=$2; shift 2;;
--baseurl) baseurl=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
# make sure mandatory args are given and valid
if [ "$(id -u)" != "0" ]; then
echo "This script should be run as 'root'"
exit 1
fi
if [ -n "$baseurl" ]; then
if [ "$arch" = "" -o "$container_release_version" = "" ]; then
echo "The --arch and --release must be specified when using --baseurl"
usage
exit 1
fi
fi
if [ "$arch" = "" ]; then
arch=$(uname -m)
fi
if [ -n "$patch_rootfs" ]; then
container_rootfs="$patch_rootfs"
container_release_get $container_rootfs
container_rootfs_patch
exit 0
fi
if [ -z $name ]; then
echo "Container name must be given"
usage
exit 1
fi
if [ -z $cfg_dir ]; then
echo "Configuration directory must be given, check lxc-create"
usage
exit 1
fi
basearch=$arch
if [ "$arch" != "sparc64" ]; then
echo "Bad architecture given, check lxc-create"
usage
exit 1
fi
if [ -f /etc/sparclinux-release ]; then
host_distribution="SPARCLinux"
host_release_version=`cat /etc/sparclinux-release |awk '{print $5}'`
host_release_major=`echo $host_release_version |awk -F '.' '{print $1}'`
host_release_minor=`echo $host_release_version |awk -F '.' '{print $2}'`
else
echo "Unable to determine host distribution"
exit 1
fi
echo "Host is $host_distribution $host_release_version"
if [ -z "$container_rootfs" ]; then
container_rootfs="$cfg_dir/rootfs"
fi
if [ -n "$template_rootfs" ]; then
container_release_get $template_rootfs
else
if [ -z "$container_release_version" ]; then
if [ $host_distribution = "SPARCLinux" ]; then
container_release_version=$host_release_version
else
echo "No release specified with -R, defaulting to 1.latest"
container_release_version="1.latest"
fi
fi
container_release_major=`echo $container_release_version |awk -F '.' '{print $1}'`
container_release_minor=`echo $container_release_version |awk -F '.' '{print $2}'`
fi
container_config_create
if [ -n "$template_rootfs" ]; then
container_rootfs_clone
else
container_rootfs_create
fi
container_release_get $container_rootfs
container_rootfs_configure
echo "Container : $container_rootfs"
echo "Config : $cfg_dir/config"
echo "Network : eth0 ($lxc_network_type) on $lxc_network_link"

276
templates/lxc-sshd.in Normal file
View File

@ -0,0 +1,276 @@
#!/bin/bash
#
# lxc: linux Container library
# Authors:
# Daniel Lezcano <daniel.lezcano@free.fr>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# Detect use under userns (unsupported)
for arg in "$@"; do
[ "$arg" = "--" ] && break
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
echo "This template can't be used for unprivileged containers." 1>&2
echo "You may want to try the \"download\" template instead." 1>&2
exit 1
fi
done
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
install_sshd()
{
rootfs=$1
tree="\
$rootfs/var/empty/sshd \
$rootfs/var/lib/empty/sshd \
$rootfs/etc/init.d \
$rootfs/etc/rc.d \
$rootfs/etc/ssh \
$rootfs/etc/sysconfig/network-scripts \
$rootfs/dev/shm \
$rootfs/run/sshd \
$rootfs/proc \
$rootfs/sys \
$rootfs/bin \
$rootfs/sbin \
$rootfs/usr \
$rootfs/tmp \
$rootfs/home \
$rootfs/root \
$rootfs/lib \
$rootfs/lib64"
mkdir -p $tree
if [ $? -ne 0 ]; then
return 1
fi
ln -s /run $rootfs/var/run
if [ $? -ne 0 ]; then
return 1
fi
return 0
}
configure_sshd()
{
rootfs=$1
cat <<EOF > $rootfs/etc/passwd
root:x:0:0:root:/root:/bin/bash
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
EOF
cat <<EOF > $rootfs/etc/group
root:x:0:root
sshd:x:74:
EOF
ssh-keygen -t rsa -N "" -f $rootfs/etc/ssh/ssh_host_rsa_key
ssh-keygen -t dsa -N "" -f $rootfs/etc/ssh/ssh_host_dsa_key
# by default setup root password with no password
cat <<EOF > $rootfs/etc/ssh/sshd_config
Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
UsePrivilegeSeparation yes
SyslogFacility AUTH
LogLevel INFO
LoginGraceTime 120
PermitRootLogin yes
StrictModes yes
PubkeyAuthentication yes
IgnoreRhosts yes
HostbasedAuthentication no
PermitEmptyPasswords yes
ChallengeResponseAuthentication no
EOF
if [ -n "$auth_key" -a -f "$auth_key" ]; then
u_path="/root/.ssh"
root_u_path="$rootfs/$u_path"
mkdir -p $root_u_path
cp $auth_key "$root_u_path/authorized_keys"
chown -R 0:0 "$rootfs/$u_path"
chmod 700 "$rootfs/$u_path"
echo "Inserted SSH public key from $auth_key into $rootfs/$u_path"
fi
return 0
}
copy_configuration()
{
path=$1
rootfs=$2
name=$3
init_path=$(realpath --relative-to=/ $(readlink -f /sbin/init))
grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs" >> $path/config
cat <<EOF >> $path/config
lxc.uts.name = $name
lxc.pty.max = 1024
lxc.cap.drop = sys_module mac_admin mac_override sys_time
# When using LXC with apparmor, uncomment the next line to run unconfined:
#lxc.apparmor.profile = unconfined
lxc.mount.entry = /dev dev none ro,bind 0 0
lxc.mount.entry = /lib lib none ro,bind 0 0
lxc.mount.entry = /bin bin none ro,bind 0 0
lxc.mount.entry = /usr usr none ro,bind 0 0
lxc.mount.entry = /sbin sbin none ro,bind 0 0
lxc.mount.entry = tmpfs run/sshd tmpfs mode=0644 0 0
lxc.mount.entry = @LXCTEMPLATEDIR@/lxc-sshd $init_path none ro,bind 0 0
lxc.mount.entry = /etc/init.d etc/init.d none ro,bind 0 0
lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
EOF
# Oracle Linux and Fedora need the following two bind mounted
if [ -d /etc/sysconfig/network-scripts ]; then
cat <<EOF >> $path/config
lxc.mount.entry = /etc/sysconfig/network-scripts etc/sysconfig/network-scripts none ro,bind 0 0
EOF
fi
if [ -d /etc/rc.d ]; then
cat <<EOF >> $path/config
lxc.mount.entry = /etc/rc.d etc/rc.d none ro,bind 0 0
EOF
fi
# if no .ipv4 section in config, then have the container run dhcp
grep -q "^lxc.net.0.ipv4.address" $path/config || touch $rootfs/run-dhcp
if [ "$(uname -m)" = "x86_64" ]; then
cat <<EOF >> $path/config
lxc.mount.entry = /lib64 lib64 none ro,bind 0 0
EOF
fi
}
usage()
{
cat <<EOF
$1 -h|--help -p|--path=<path> [--rootfs=<path>]
EOF
return 0
}
check_for_cmd()
{
cmd_path=`type $1`
if [ $? -ne 0 ]; then
echo "The command '$1' $cmd_path is not accessible on the system"
exit 1
fi
# we use cut instead of awk because awk is alternatives symlink on ubuntu
# and /etc/alternatives isn't bind mounted
cmd_path=`echo $cmd_path |cut -d ' ' -f 3`
}
options=$(getopt -o hp:n:S: -l help,rootfs:,path:,name:,auth-key: -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
fi
eval set -- "$options"
while true
do
case "$1" in
-h|--help) usage $0 && exit 0;;
-p|--path) path=$2; shift 2;;
--rootfs) rootfs=$2; shift 2;;
-n|--name) name=$2; shift 2;;
-S|--auth-key) auth_key=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
if [ "$(id -u)" != "0" ]; then
echo "This script should be run as 'root'"
exit 1
fi
if [ $0 = "/sbin/init" ]; then
PATH="$PATH:/bin:/sbin:/usr/sbin"
check_for_cmd @SBINDIR@/init.lxc
check_for_cmd sshd
sshd_path=$cmd_path
# run dhcp?
if [ -f /run-dhcp ]; then
check_for_cmd dhclient
check_for_cmd ifconfig
touch /etc/fstab
rm -f /dhclient.conf
cat > /dhclient.conf << EOF
send host-name = gethostname();
EOF
ifconfig eth0 up
dhclient eth0 -cf /dhclient.conf
echo "Container IP address:"
ifconfig eth0 |grep inet
fi
exec @SBINDIR@/init.lxc -- $sshd_path
exit 1
fi
if [ -z "$path" ]; then
echo "'path' parameter is required"
exit 1
fi
# detect rootfs
config="$path/config"
if [ -z "$rootfs" ]; then
if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then
rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config)
else
rootfs=$path/rootfs
fi
fi
install_sshd $rootfs
if [ $? -ne 0 ]; then
echo "failed to install sshd's rootfs"
exit 1
fi
configure_sshd $rootfs
if [ $? -ne 0 ]; then
echo "failed to configure sshd template"
exit 1
fi
copy_configuration $path $rootfs $name
if [ $? -ne 0 ]; then
echo "failed to write configuration file"
exit 1
fi

View File

@ -0,0 +1,374 @@
#!/bin/bash
# template script for generating ubuntu container for LXC based on released
# cloud images.
#
# Copyright © 2012 Serge Hallyn <serge.hallyn@canonical.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
set -e
STATE_DIR="@LOCALSTATEDIR@"
HOOK_DIR="@LXCHOOKDIR@"
CLONE_HOOK_FN="$HOOK_DIR/ubuntu-cloud-prep"
LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
KNOWN_RELEASES="precise trusty xenial yakkety zesty"
skip_arch_check=${UCTEMPLATE_SKIP_ARCH_CHECK:-0}
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
if [ -r /etc/default/lxc ]; then
. /etc/default/lxc
fi
am_in_userns() {
[ -e /proc/self/uid_map ] || { echo no; return; }
[ "$(wc -l /proc/self/uid_map | awk '{ print $1 }')" -eq 1 ] || { echo yes; return; }
line=$(awk '{ print $1 " " $2 " " $3 }' /proc/self/uid_map)
[ "$line" = "0 0 4294967295" ] && { echo no; return; }
echo yes
}
in_userns=0
[ $(am_in_userns) = "yes" ] && in_userns=1
copy_configuration()
{
path=$1
rootfs=$2
name=$3
arch=$4
release=$5
if [ $arch = "i386" ]; then
arch="i686"
fi
# if there is exactly one veth network entry, make sure it has an
# associated hwaddr.
nics=`grep -e '^lxc\.net\.0\.type[ \t]*=[ \t]*veth' $path/config | wc -l`
if [ $nics -eq 1 ]; then
grep -q "^lxc.net.0.hwaddr" $path/config || sed -i -e "/^lxc\.net\.0\.type[ \t]*=[ \t]*veth/a lxc.net.0.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" $path/config
fi
# Generate the configuration file
## Relocate all the network config entries
sed -i -e "/lxc.net.0/{w ${path}/config-network" -e "d}" $path/config
## Relocate any other config entries
sed -i -e "/lxc./{w ${path}/config-auto" -e "d}" $path/config
## Add all the includes
echo "" >> $path/config
echo "# Common configuration" >> $path/config
if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.common.conf" ]; then
echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.common.conf" >> $path/config
fi
if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.${release}.conf" ]; then
echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.${release}.conf" >> $path/config
fi
if [ $in_userns -eq 1 ] && [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.userns.conf" ]; then
echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.userns.conf" >> $path/config
fi
## Add the container-specific config
echo "" >> $path/config
echo "# Container specific configuration" >> $path/config
[ -e "$path/config-auto" ] && cat $path/config-auto >> $path/config && rm $path/config-auto
grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs" >> $path/config
cat <<EOF >> $path/config
lxc.uts.name = $name
lxc.arch = $arch
EOF
## Re-add the previously removed network config
echo "" >> $path/config
echo "# Network configuration" >> $path/config
cat $path/config-network >> $path/config
rm $path/config-network
# Set initial timezone as on host
if [ -f /etc/timezone ]; then
cat /etc/timezone > $rootfs/etc/timezone
chroot $rootfs dpkg-reconfigure -f noninteractive tzdata
elif [ -f /etc/sysconfig/clock ]; then
. /etc/sysconfig/clock
echo $ZONE > $rootfs/etc/timezone
chroot $rootfs dpkg-reconfigure -f noninteractive tzdata
else
echo "Timezone in container is not configured. Adjust it manually."
fi
# rmdir /dev/shm for containers that have /run/shm
# I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did
# get bind mounted to the host's /run/shm. So try to rmdir
# it, and in case that fails move it out of the way.
# NOTE: This can only be removed once 12.04 goes out of support
if [ ! -L $rootfs/dev/shm ] && [ -e $rootfs/dev/shm ]; then
rmdir $rootfs/dev/shm 2>/dev/null || mv $rootfs/dev/shm $rootfs/dev/shm.bak
ln -s /run/shm $rootfs/dev/shm
fi
return 0
}
usage()
{
cat <<EOF
LXC Container configuration for Ubuntu Cloud images.
Generic Options
[ -r | --release <release> ]: Release name of container, defaults to host
[ --rootfs <path> ]: Path in which rootfs will be placed
[ -a | --arch ]: Architecture of container, defaults to host architecture
[ -T | --tarball ]: Location of tarball
[ -d | --debug ]: Run with 'set -x' to debug errors
[ -s | --stream]: Use specified stream rather than 'tryreleased'
Additionally, clone hooks can be passed through (ie, --userdata). For those,
see:
$CLONE_HOOK_FN --help
EOF
return 0
}
options=$(getopt -o a:hp:r:n:Fi:CLS:T:ds:u: -l arch:,help,rootfs:,path:,release:,name:,flush-cache,hostid:,auth-key:,cloud,no_locales,tarball:,debug,stream:,userdata:,vendordata:,mapped-uid:,mapped-gid: -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
fi
eval set -- "$options"
mapped_uid=-1
mapped_gid=-1
# default release is trusty, or the systems release if recognized
release=trusty
if [ -f /etc/lsb-release ]; then
. /etc/lsb-release
rels=$(ubuntu-distro-info --supported 2>/dev/null) ||
rels="$KNOWN_RELEASES"
for r in $rels; do
[ "$DISTRIB_CODENAME" = "$r" ] && release="$r"
done
fi
# Code taken from debootstrap
if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then
arch=`/usr/bin/dpkg --print-architecture`
elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then
arch=`/usr/bin/udpkg --print-architecture`
else
arch=$(uname -m)
if [ "$arch" = "i686" ]; then
arch="i386"
elif [ "$arch" = "x86_64" ]; then
arch="amd64"
elif [ "$arch" = "armv7l" ]; then
# note: arm images don't exist before oneiric; are called armhf in
# trusty and later; and are not supported by the query, so we don't actually
# support them yet (see check later on). When Query2 is available,
# we'll use that to enable arm images.
arch="armhf"
elif [ "$arch" = "aarch64" ]; then
arch="arm64"
elif [ "$arch" = "ppc64le" ]; then
arch="ppc64el"
fi
fi
debug=0
hostarch=$arch
cloud=0
locales=1
flushcache=0
stream="tryreleased"
cloneargs=()
while true
do
case "$1" in
-h|--help) usage $0 && exit 1;;
-p|--path) path=$2; shift 2;;
-n|--name) name=$2; shift 2;;
-F|--flush-cache) flushcache=1; shift 1;;
-r|--release) release=$2; shift 2;;
-a|--arch) arch=$2; shift 2;;
-T|--tarball) tarball=$2; shift 2;;
-d|--debug) debug=1; shift 1;;
-s|--stream) stream=$2; shift 2;;
--rootfs) rootfs=$2; shift 2;;
-L|--no?locales) cloneargs[${#cloneargs[@]}]="--no-locales"; shift 1;;
-i|--hostid) cloneargs[${#cloneargs[@]}]="--hostid=$2"; shift 2;;
-u|--userdata) cloneargs[${#cloneargs[@]}]="--userdata=$2"; shift 2;;
-V|--vendordata) cloneargs[${#cloneargs[@]}]="--vendordata=$2"; shift 2;;
-C|--cloud) cloneargs[${#cloneargs[@]}]="--cloud"; shift 1;;
-S|--auth-key) cloneargs[${#cloneargs[@]}]="--auth-key=$2"; shift 2;;
--mapped-uid) mapped_uid=$2; shift 2;;
--mapped-gid) mapped_gid=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
cloneargs=( "--name=$name" "${cloneargs[@]}" )
if [ $debug -eq 1 ]; then
set -x
fi
if [ "$arch" = "i686" ]; then
arch=i386
fi
if [ "$skip_arch_check" = "0" ]; then
case "$hostarch:$arch" in
$arch:$arch) : ;; # the host == container
amd64:i386) :;; # supported "cross"
arm64:arm*) :;; # supported "cross"
armel:armhf) :;; # supported "cross"
armhf:armel) :;; # supported "cross"
*) echo "cannot create '$arch' container on hostarch '$hostarch'";
exit 1;;
esac
fi
if [ "$stream" != "daily" -a "$stream" != "released" -a "$stream" != "tryreleased" ]; then
echo "Only 'daily' and 'released' and 'tryreleased' streams are supported"
exit 1
fi
if [ -z "$path" ]; then
echo "'path' parameter is required"
exit 1
fi
if [ "$(id -u)" != "0" ]; then
echo "This script should be run as 'root'"
exit 1
fi
# detect rootfs
config="$path/config"
if [ -z "$rootfs" ]; then
if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then
rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config)
else
rootfs=$path/rootfs
fi
fi
type ubuntu-cloudimg-query
type wget
# determine the url, tarball, and directory names
# download if needed
# Allow the cache base to be set by environment variable
cache=${LXC_CACHE_PATH:-"$STATE_DIR/cache/lxc"}/cloud-$release
if [ $in_userns -eq 1 ]; then
STATE_DIR="$HOME/.cache/lxc"
cache=${LXC_CACHE_PATH:-"$STATE_DIR"}/cloud-$release
fi
mkdir -p $cache
if [ "$stream" = "tryreleased" ]; then
stream=released
ubuntu-cloudimg-query $release $stream $arch 1>/dev/null 2>/dev/null || stream=daily
fi
if [ -n "$tarball" ]; then
url2="$tarball"
else
if ! url1=`ubuntu-cloudimg-query $release $stream $arch --format "%{url}\n"`; then
echo "There is no download available for release=$release, stream=$stream, arch=$arch"
[ "$stream" = "daily" ] || echo "You may try with '--stream=daily'"
exit 1
fi
if [ "$release" = "precise" ] || [ "$release" = "trusty" ]; then
url2=`echo $url1 | sed -e 's/.tar.gz/-root\0/' -e 's/.tar.gz/.tar.xz/'`
else
url2=`echo $url1 | sed -e 's/.tar.gz/.squashfs/'`
fi
fi
filename=`basename $url2`
wgetcleanup()
{
rm -f $filename
}
do_extract_rootfs() {
cd $cache
if [ $flushcache -eq 1 ]; then
echo "Clearing the cached images"
rm -f $filename
fi
trap wgetcleanup EXIT SIGHUP SIGINT SIGTERM
if [ ! -f $filename ]; then
wget $url2
fi
trap EXIT
trap SIGHUP
trap SIGINT
trap SIGTERM
echo "Extracting container rootfs"
mkdir -p $rootfs
cd $rootfs
if [ "${filename##*.}" = "squashfs" ]; then
unsquashfs -n -f -d "$rootfs" "$cache/$filename"
else
if [ $in_userns -eq 1 ]; then
tar --anchored --exclude="dev/*" --numeric-owner -xpf "$cache/$filename"
mkdir -p $rootfs/dev/pts/
else
tar --numeric-owner -xpf "$cache/$filename"
fi
fi
}
if [ -n "$tarball" ]; then
do_extract_rootfs
else
mkdir -p "$STATE_DIR/lock/subsys/"
(
flock -x 9
do_extract_rootfs
) 9>"$STATE_DIR/lock/subsys/lxc-ubuntu-cloud"
fi
copy_configuration $path $rootfs $name $arch $release
"$CLONE_HOOK_FN" "${cloneargs[@]}" "$rootfs"
if [ $mapped_uid -ne -1 ]; then
chown $mapped_uid $path/config
chown -R $mapped_uid $STATE_DIR
chown -R $mapped_uid $cache
fi
if [ $mapped_gid -ne -1 ]; then
chgrp $mapped_gid $path/config
chgrp -R $mapped_gid $STATE_DIR
chgrp -R $mapped_gid $cache
fi
echo "Container $name created."
exit 0
# vi: ts=4 expandtab

877
templates/lxc-ubuntu.in Normal file
View File

@ -0,0 +1,877 @@
#!/bin/bash
#
# template script for generating ubuntu container for LXC
#
# This script consolidates and extends the existing lxc ubuntu scripts
#
# Copyright © 2011 Serge Hallyn <serge.hallyn@canonical.com>
# Copyright © 2010 Wilhelm Meier
# Author: Wilhelm Meier <wilhelm.meier@fh-kl.de>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# Detect use under userns (unsupported)
for arg in "$@"; do
[ "$arg" = "--" ] && break
if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
echo "This template can't be used for unprivileged containers." 1>&2
echo "You may want to try the \"download\" template instead." 1>&2
exit 1
fi
done
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
set -e
LOCALSTATEDIR="@LOCALSTATEDIR@"
LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
# Allows the lxc-cache directory to be set by environment variable
LXC_CACHE_PATH=${LXC_CACHE_PATH:-"$LOCALSTATEDIR/cache/lxc"}
if [ -r /etc/default/lxc ]; then
. /etc/default/lxc
fi
# Check if given path is in a btrfs partition
is_btrfs()
{
[ -e $1 -a $(stat -f -c '%T' $1) = "btrfs" ]
}
# Check if given path is the root of a btrfs subvolume
is_btrfs_subvolume()
{
[ -d $1 -a $(stat -f -c '%T' $1) = "btrfs" -a $(stat -c '%i' $1) -eq 256 ]
}
try_mksubvolume()
{
path=$1
[ -d $path ] && return 0
mkdir -p $(dirname $path)
if which btrfs >/dev/null 2>&1 && is_btrfs $(dirname $path); then
btrfs subvolume create $path
else
mkdir -p $path
fi
}
try_rmsubvolume()
{
path=$1
[ -d $path ] || return 0
if which btrfs >/dev/null 2>&1 && is_btrfs_subvolume $path; then
btrfs subvolume delete $path
else
rm -rf $path
fi
}
configure_ubuntu()
{
rootfs=$1
hostname=$2
release=$3
user=$4
password=$5
# configure the network using the dhcp
if chroot $rootfs which netplan >/dev/null 2>&1; then
cat <<EOF > $rootfs/etc/netplan/10-lxc.yaml
network:
ethernets:
eth0: {dhcp4: true}
version: 2
EOF
else
cat <<EOF > $rootfs/etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
# The loopback network interface
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
EOF
fi
# set the hostname
cat <<EOF > $rootfs/etc/hostname
$hostname
EOF
# set minimal hosts
cat <<EOF > $rootfs/etc/hosts
127.0.0.1 localhost
127.0.1.1 $hostname
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
EOF
if [ ! -f $rootfs/etc/init/container-detect.conf ]; then
# suppress log level output for udev
sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf
# remove jobs for consoles 5 and 6 since we only create 4 consoles in
# this template
rm -f $rootfs/etc/init/tty{5,6}.conf
fi
if [ -z "$bindhome" ]; then
chroot $rootfs useradd --create-home -s /bin/bash $user
echo "$user:$password" | chroot $rootfs chpasswd
fi
# make sure we have the current locale defined in the container
if [ -z "$LANG" ] || echo $LANG | grep -E -q "^C(\..+)*$"; then
chroot $rootfs locale-gen en_US.UTF-8 || true
chroot $rootfs update-locale LANG=en_US.UTF-8 || true
else
chroot $rootfs locale-gen $LANG || true
chroot $rootfs update-locale LANG=$LANG || true
fi
# generate new SSH keys
if [ -x $rootfs/var/lib/dpkg/info/openssh-server.postinst ]; then
cat > $rootfs/usr/sbin/policy-rc.d << EOF
#!/bin/sh
exit 101
EOF
chmod +x $rootfs/usr/sbin/policy-rc.d
if [ -f "$rootfs/etc/init/ssh.conf" ]; then
mv "$rootfs/etc/init/ssh.conf" "$rootfs/etc/init/ssh.conf.disabled"
fi
rm -f $rootfs/etc/ssh/ssh_host_*key*
DPKG_MAINTSCRIPT_PACKAGE=openssh DPKG_MAINTSCRIPT_NAME=postinst chroot $rootfs /var/lib/dpkg/info/openssh-server.postinst configure
sed -i "s/root@$(hostname)/root@$hostname/g" $rootfs/etc/ssh/ssh_host_*.pub
if [ -f "$rootfs/etc/init/ssh.conf.disabled" ]; then
mv "$rootfs/etc/init/ssh.conf.disabled" "$rootfs/etc/init/ssh.conf"
fi
rm -f $rootfs/usr/sbin/policy-rc.d
fi
return 0
}
# finish setting up the user in the container by injecting ssh key and
# adding sudo group membership.
# passed-in user is either 'ubuntu' or the user to bind in from host.
finalize_user()
{
user=$1
sudo_version=$(chroot $rootfs dpkg-query -W -f='${Version}' sudo)
if chroot $rootfs dpkg --compare-versions $sudo_version gt "1.8.3p1-1"; then
groups="sudo"
else
groups="sudo admin"
fi
for group in $groups; do
chroot $rootfs groupadd --system $group >/dev/null 2>&1 || true
chroot $rootfs adduser ${user} $group >/dev/null 2>&1 || true
done
if [ -n "$auth_key" -a -f "$auth_key" ]; then
u_path="/home/${user}/.ssh"
root_u_path="$rootfs/$u_path"
mkdir -p $root_u_path
cp $auth_key "$root_u_path/authorized_keys"
chroot $rootfs chown -R ${user}: "$u_path"
echo "Inserted SSH public key from $auth_key into /home/${user}/.ssh/authorized_keys"
fi
return 0
}
# A function to try and autodetect squid-deb-proxy servers on the local network
# if either the squid-deb-proxy-client package is installed on the host or
# a parent container set the 50squid-deb-proxy-client file.
squid_deb_proxy_autodetect()
{
local apt_discover=/usr/share/squid-deb-proxy-client/apt-avahi-discover
local proxy_file=/etc/apt/apt.conf.d/50squid-deb-proxy-client
squid_proxy_line= # That's a global :/
# Maybe the host is aware of a squid-deb-proxy?
if [ -f $apt_discover ]; then
echo -n "Discovering squid-deb-proxy..."
squid_proxy_line=$($apt_discover)
if [ -n "$squid_proxy_line" ]; then
echo "found squid-deb-proxy: $squid_proxy_line"
else
echo "no squid-deb-proxy found"
fi
fi
# Are we in a nested container, and the parent already knows of a proxy?
if [ -f $proxy_file ]; then
# Extract the squid URL from the file (whatever is between "")
squid_proxy_line=`cat $proxy_file | sed "s/.*\"\(.*\)\".*/\1/"`
fi
}
#
# Choose proxies for container
# http_proxy will be used by debootstrap on the host.
# APT_PROXY will be used to set /etc/apt/apt.conf.d/70proxy in the container.
#
choose_container_proxy()
{
local rootfs=$1
local arch=$2
if [ -z "$HTTP_PROXY" ]; then
HTTP_PROXY="none"
fi
case "$HTTP_PROXY" in
none)
squid_deb_proxy_autodetect
if [ -n "$squid_proxy_line" ]; then
APT_PROXY=$squid_proxy_line
export http_proxy=$squid_proxy_line
else
APT_PROXY=
fi
;;
apt)
RES=`apt-config shell APT_PROXY Acquire::http::Proxy`
eval $RES
[ -z "$APT_PROXY" ] || export http_proxy=$APT_PROXY
;;
*)
APT_PROXY=$HTTP_PROXY
export http_proxy=$HTTP_PROXY
;;
esac
}
write_sourceslist()
{
# $1 => path to the partial cache or the rootfs
# $2 => architecture we want to add
# $3 => whether to use the multi-arch syntax or not
if [ -n "$APT_PROXY" ]; then
mkdir -p $1/etc/apt/apt.conf.d
cat > $1/etc/apt/apt.conf.d/70proxy << EOF
Acquire::http::Proxy "$APT_PROXY" ;
EOF
fi
case $2 in
amd64|i386)
MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu}
SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.ubuntu.com/ubuntu}
;;
*)
MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
;;
esac
if [ -n "$3" ]; then
cat >> "$1/etc/apt/sources.list" << EOF
deb [arch=$2] $MIRROR ${release} main restricted universe multiverse
deb [arch=$2] $MIRROR ${release}-updates main restricted universe multiverse
deb [arch=$2] $SECURITY_MIRROR ${release}-security main restricted universe multiverse
EOF
else
cat >> "$1/etc/apt/sources.list" << EOF
deb $MIRROR ${release} main restricted universe multiverse
deb $MIRROR ${release}-updates main restricted universe multiverse
deb $SECURITY_MIRROR ${release}-security main restricted universe multiverse
EOF
fi
}
install_packages()
{
local rootfs="$1"
shift
local packages="$*"
if [ -z $update ]
then
chroot $rootfs apt-get update
update=true
fi
if [ -n "${packages}" ]
then
chroot $rootfs apt-get install --force-yes -y --no-install-recommends ${packages}
fi
}
cleanup()
{
try_rmsubvolume $cache/partial-$arch
try_rmsubvolume $cache/rootfs-$arch
}
suggest_flush()
{
echo "Container upgrade failed. The container cache may be out of date,"
echo "in which case flushing the cache (see -F in the help output) may help."
}
download_ubuntu()
{
cache=$1
arch=$2
release=$3
case $2 in
amd64|i386)
MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu}
SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.ubuntu.com/ubuntu}
;;
*)
MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
;;
esac
packages_template=${packages_template:-"apt-transport-https,ssh,vim"}
debootstrap_parameters=
# Try to guess a list of langpacks to install
langpacks="language-pack-en"
if which dpkg >/dev/null 2>&1; then
langpacks=`(echo $langpacks &&
dpkg -l | grep -E "^ii language-pack-[a-z]* " |
cut -d ' ' -f3) | sort -u`
fi
packages_template="${packages_template},$(echo $langpacks | sed 's/ /,/g')"
if [ -n "$variant" ]; then
debootstrap_parameters="$debootstrap_parameters --variant=$variant"
fi
if [ "$variant" = 'minbase' ]; then
packages_template="${packages_template},sudo"
# Newer releases use netplan, EOL releases not supported
case $release in
trusty|xenial|zesty)
packages_template="${packages_template},ifupdown,isc-dhcp-client"
;;
esac
fi
echo "Installing packages in template: ${packages_template}"
trap cleanup EXIT SIGHUP SIGINT SIGTERM
# check the mini ubuntu was not already downloaded
try_mksubvolume "$cache/partial-$arch"
if [ $? -ne 0 ]; then
echo "Failed to create '$cache/partial-$arch' directory"
return 1
fi
choose_container_proxy $cache/partial-$arch/ $arch
# download a mini ubuntu into a cache
echo "Downloading ubuntu $release minimal ..."
if [ -n "$(which qemu-debootstrap)" ]; then
qemu-debootstrap --verbose $debootstrap_parameters --components=main,universe --arch=$arch --include=${packages_template} $release $cache/partial-$arch $MIRROR
else
debootstrap --verbose $debootstrap_parameters --components=main,universe --arch=$arch --include=${packages_template} $release $cache/partial-$arch $MIRROR
fi
if [ $? -ne 0 ]; then
echo "Failed to download the rootfs, aborting."
return 1
fi
# Serge isn't sure whether we should avoid doing this when
# $release == `distro-info -d`
echo "Installing updates"
> $cache/partial-$arch/etc/apt/sources.list
write_sourceslist $cache/partial-$arch/ $arch
chroot "$1/partial-${arch}" apt-get update
if [ $? -ne 0 ]; then
echo "Failed to update the apt cache"
return 1
fi
cat > "$1/partial-${arch}"/usr/sbin/policy-rc.d << EOF
#!/bin/sh
exit 101
EOF
chmod +x "$1/partial-${arch}"/usr/sbin/policy-rc.d
(
cat << EOF
mount -t proc proc "${1}/partial-${arch}/proc"
chroot "${1}/partial-${arch}" apt-get dist-upgrade -y
EOF
) | lxc-unshare -s MOUNT -- sh -eu || (suggest_flush; false)
rm -f "$1/partial-${arch}"/usr/sbin/policy-rc.d
chroot "$1/partial-${arch}" apt-get clean
mv "$1/partial-$arch" "$1/rootfs-$arch"
trap EXIT
trap SIGINT
trap SIGTERM
trap SIGHUP
echo "Download complete"
return 0
}
copy_ubuntu()
{
cache=$1
arch=$2
rootfs=$3
# make a local copy of the miniubuntu
echo "Copying rootfs to $rootfs ..."
try_mksubvolume $rootfs
if which btrfs >/dev/null 2>&1 && is_btrfs_subvolume $cache/rootfs-$arch && is_btrfs_subvolume $rootfs; then
realrootfs=$(dirname $config)/rootfs
[ "$rootfs" = "$realrootfs" ] || umount $rootfs || return 1
btrfs subvolume delete $realrootfs || return 1
btrfs subvolume snapshot $cache/rootfs-$arch $realrootfs || return 1
[ "$rootfs" = "$realrootfs" ] || mount --bind $realrootfs $rootfs || return 1
else
rsync -SHaAX $cache/rootfs-$arch/ $rootfs/ || return 1
fi
return 0
}
install_ubuntu()
{
rootfs=$1
release=$2
flushcache=$3
cache="$4/$release"
mkdir -p $LOCALSTATEDIR/lock/subsys/
(
flock -x 9
if [ $? -ne 0 ]; then
echo "Cache repository is busy."
return 1
fi
if [ $flushcache -eq 1 ]; then
echo "Flushing cache..."
try_rmsubvolume $cache/partial-$arch
try_rmsubvolume $cache/rootfs-$arch
fi
echo "Checking cache download in $cache/rootfs-$arch ... "
if [ ! -e "$cache/rootfs-$arch" ]; then
download_ubuntu $cache $arch $release
if [ $? -ne 0 ]; then
echo "Failed to download 'ubuntu $release base'"
return 1
fi
fi
echo "Copy $cache/rootfs-$arch to $rootfs ... "
copy_ubuntu $cache $arch $rootfs
if [ $? -ne 0 ]; then
echo "Failed to copy rootfs"
return 1
fi
return 0
) 9>$LOCALSTATEDIR/lock/subsys/lxc-ubuntu$release
return $?
}
copy_configuration()
{
path=$1
rootfs=$2
name=$3
arch=$4
release=$5
if [ $arch = "i386" ]; then
arch="i686"
fi
# if there is exactly one veth network entry, make sure it has an
# associated hwaddr.
nics=`grep -e '^lxc\.net\.0\.type[ \t]*=[ \t]*veth' $path/config | wc -l`
if [ $nics -eq 1 ]; then
grep -q "^lxc.net.0.hwaddr" $path/config || sed -i -e "/^lxc\.net\.0\.type[ \t]*=[ \t]*veth/a lxc.net.0.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" $path/config
fi
# Generate the configuration file
## Relocate all the network config entries
sed -i -e "/lxc.net.0/{w ${path}/config-network" -e "d}" $path/config
## Relocate any other config entries
sed -i -e "/lxc./{w ${path}/config-auto" -e "d}" $path/config
## Add all the includes
echo "" >> $path/config
echo "# Common configuration" >> $path/config
if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu.common.conf" ]; then
echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.common.conf" >> $path/config
fi
if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu.${release}.conf" ]; then
echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.${release}.conf" >> $path/config
fi
## Add the container-specific config
echo "" >> $path/config
echo "# Container specific configuration" >> $path/config
[ -e "$path/config-auto" ] && cat $path/config-auto >> $path/config && rm $path/config-auto
grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs" >> $path/config
cat <<EOF >> $path/config
lxc.uts.name = $name
lxc.arch = $arch
EOF
## Re-add the previously removed network config
echo "" >> $path/config
echo "# Network configuration" >> $path/config
cat $path/config-network >> $path/config
rm $path/config-network
if [ $? -ne 0 ]; then
echo "Failed to add configuration"
return 1
fi
return 0
}
post_process()
{
rootfs=$1
release=$2
packages=$3
# Disable service startup
cat > $rootfs/usr/sbin/policy-rc.d << EOF
#!/bin/sh
exit 101
EOF
chmod +x $rootfs/usr/sbin/policy-rc.d
# If the container isn't running a native architecture, setup multiarch
if [ -x "$(ls -1 ${rootfs}/usr/bin/qemu-*-static 2>/dev/null)" ]; then
dpkg_version=$(chroot $rootfs dpkg-query -W -f='${Version}' dpkg)
if chroot $rootfs dpkg --compare-versions $dpkg_version ge "1.16.2"; then
chroot $rootfs dpkg --add-architecture ${hostarch}
else
mkdir -p ${rootfs}/etc/dpkg/dpkg.cfg.d
echo "foreign-architecture ${hostarch}" > ${rootfs}/etc/dpkg/dpkg.cfg.d/lxc-multiarch
fi
# Save existing value of MIRROR and SECURITY_MIRROR
DEFAULT_MIRROR=$MIRROR
DEFAULT_SECURITY_MIRROR=$SECURITY_MIRROR
# Write a new sources.list containing both native and multiarch entries
> ${rootfs}/etc/apt/sources.list
write_sourceslist $rootfs $arch "native"
MIRROR=$DEFAULT_MIRROR
SECURITY_MIRROR=$DEFAULT_SECURITY_MIRROR
write_sourceslist $rootfs $hostarch "multiarch"
# Finally update the lists and install upstart using the host architecture
HOST_PACKAGES="upstart:${hostarch} mountall:${hostarch} isc-dhcp-client:${hostarch}"
chroot $rootfs apt-get update
if chroot $rootfs dpkg -l iproute2 | grep -q ^ii; then
HOST_PACKAGES="$HOST_PACKAGES iproute2:${hostarch}"
else
HOST_PACKAGES="$HOST_PACKAGES iproute:${hostarch}"
fi
install_packages $rootfs $HOST_PACKAGES
fi
# Install Packages in container
if [ -n "$packages" ]
then
local packages="`echo $packages | sed 's/,/ /g'`"
echo "Installing packages: ${packages}"
install_packages $rootfs $packages
fi
# Set initial timezone as on host
if [ -f /etc/timezone ]; then
cat /etc/timezone > $rootfs/etc/timezone
chroot $rootfs dpkg-reconfigure -f noninteractive tzdata
elif [ -f /etc/sysconfig/clock ]; then
. /etc/sysconfig/clock
echo $ZONE > $rootfs/etc/timezone
chroot $rootfs dpkg-reconfigure -f noninteractive tzdata
else
echo "Timezone in container is not configured. Adjust it manually."
fi
# rmdir /dev/shm for containers that have /run/shm
# I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did
# get bind mounted to the host's /run/shm. So try to rmdir
# it, and in case that fails move it out of the way.
# NOTE: This can only be removed once 12.04 goes out of support
if [ ! -L $rootfs/dev/shm ] && [ -e $rootfs/dev/shm ]; then
rmdir $rootfs/dev/shm 2>/dev/null || mv $rootfs/dev/shm $rootfs/dev/shm.bak
ln -s /run/shm $rootfs/dev/shm
fi
# Re-enable service startup
rm $rootfs/usr/sbin/policy-rc.d
}
do_bindhome()
{
rootfs=$1
user=$2
# copy /etc/passwd, /etc/shadow, and /etc/group entries into container
pwd=`getent passwd $user` || { echo "Failed to copy password entry for $user"; false; }
echo $pwd >> $rootfs/etc/passwd
# make sure user's shell exists in the container
shell=`echo $pwd | cut -d: -f 7`
if [ ! -x $rootfs/$shell ]; then
echo "shell $shell for user $user was not found in the container."
pkg=`dpkg -S $(readlink -m $shell) | cut -d ':' -f1`
echo "Installing $pkg"
install_packages $rootfs $pkg
fi
shad=`getent shadow $user`
echo "$shad" >> $rootfs/etc/shadow
# bind-mount the user's path into the container's /home
h=`getent passwd $user | cut -d: -f 6`
mkdir -p $rootfs/$h
# use relative path in container
h2=${h#/}
while [ ${h2:0:1} = "/" ]; do
h2=${h2#/}
done
echo "lxc.mount.entry = $h $h2 none bind 0 0" >> $path/config
# Make sure the group exists in container
grp=`echo $pwd | cut -d: -f 4` # group number for $user
grpe=`getent group $grp` || return 0 # if host doesn't define grp, ignore in container
chroot $rootfs getent group "$grpe" || echo "$grpe" >> $rootfs/etc/group
}
usage()
{
cat <<EOF
$1 -h|--help [-a|--arch] [-b|--bindhome <user>] [-d|--debug]
[-F | --flush-cache] [-r|--release <release>] [-v|--variant] [ -S | --auth-key <keyfile>]
[--rootfs <rootfs>] [--packages <packages>] [-u|--user <user>] [--password <password>]
[--mirror <url>] [--security-mirror <url>]
release: the ubuntu release (e.g. xenial): defaults to host release on ubuntu, otherwise uses latest LTS
variant: debootstrap variant to use (see debootstrap(8))
bindhome: bind <user>'s home into the container
The ubuntu user will not be created, and <user> will have
sudo access.
arch: the container architecture (e.g. amd64): defaults to host arch
auth-key: SSH Public key file to inject into container
packages: list of packages to add comma separated
mirror,security-mirror: mirror for download and /etc/apt/sources.list
EOF
return 0
}
options=$(getopt -o a:b:hp:r:v:n:FS:du: -l arch:,bindhome:,help,path:,release:,variant:,name:,flush-cache,auth-key:,debug,rootfs:,packages:,user:,password:,mirror:,security-mirror: -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
fi
eval set -- "$options"
release=xenial # Default to the last Ubuntu LTS release for non-Ubuntu systems
if [ -f /etc/lsb-release ]; then
. /etc/lsb-release
if [ "$DISTRIB_ID" = "Ubuntu" ]; then
release=$DISTRIB_CODENAME
fi
fi
bindhome=
# Code taken from debootstrap
if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then
arch=`/usr/bin/dpkg --print-architecture`
elif which udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then
arch=`/usr/bin/udpkg --print-architecture`
else
arch=$(uname -m)
if [ "$arch" = "i686" ]; then
arch="i386"
elif [ "$arch" = "x86_64" ]; then
arch="amd64"
elif [ "$arch" = "armv7l" ]; then
arch="armhf"
elif [ "$arch" = "aarch64" ]; then
arch="arm64"
elif [ "$arch" = "ppc64le" ]; then
arch="ppc64el"
fi
fi
debug=0
hostarch=$arch
flushcache=0
packages=""
user="ubuntu"
password="ubuntu"
while true
do
case "$1" in
-h|--help) usage $0 && exit 0;;
--rootfs) rootfs=$2; shift 2;;
-p|--path) path=$2; shift 2;;
-n|--name) name=$2; shift 2;;
-u|--user) user=$2; shift 2;;
--password) password=$2; shift 2;;
-F|--flush-cache) flushcache=1; shift 1;;
-r|--release) release=$2; shift 2;;
-v|--variant) variant=$2; shift 2;;
--packages) packages=$2; shift 2;;
-b|--bindhome) bindhome=$2; shift 2;;
-a|--arch) arch=$2; shift 2;;
-S|--auth-key) auth_key=$2; shift 2;;
-d|--debug) debug=1; shift 1;;
--mirror) MIRROR=$2; shift 2;;
--security-mirror) SECURITY_MIRROR=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
if [ $debug -eq 1 ]; then
set -x
fi
if [ -n "$bindhome" ]; then
pwd=`getent passwd $bindhome`
if [ $? -ne 0 ]; then
echo "Error: no password entry found for $bindhome"
exit 1
fi
fi
if [ "$arch" = "i686" ]; then
arch=i386
fi
if [ $hostarch = "i386" -a $arch = "amd64" ]; then
echo "can't create $arch container on $hostarch"
exit 1
fi
if [ $hostarch = "armhf" -o $hostarch = "armel" -o $hostarch = "arm64" ] && \
[ $arch != "armhf" -a $arch != "armel" -a $arch != "arm64" ]; then
echo "can't create $arch container on $hostarch"
exit 1
fi
if [ $arch = "arm64" ] && [ $hostarch != "arm64" ]; then
echo "can't create $arch container on $hostarch"
exit 1
fi
if [ $hostarch = "powerpc" -a $arch != "powerpc" ]; then
echo "can't create $arch container on $hostarch"
exit 1
fi
which debootstrap >/dev/null 2>&1 || { echo "'debootstrap' command is missing" >&2; false; }
if [ -z "$path" ]; then
echo "'path' parameter is required"
exit 1
fi
if [ "$(id -u)" != "0" ]; then
echo "This script should be run as 'root'"
exit 1
fi
# detect rootfs
config="$path/config"
# if $rootfs exists here, it was passed in with --rootfs
if [ -z "$rootfs" ]; then
if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then
rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config)
else
rootfs=$path/rootfs
fi
fi
install_ubuntu $rootfs $release $flushcache $LXC_CACHE_PATH
if [ $? -ne 0 ]; then
echo "failed to install ubuntu $release"
exit 1
fi
configure_ubuntu $rootfs $name $release $user $password
if [ $? -ne 0 ]; then
echo "failed to configure ubuntu $release for a container"
exit 1
fi
copy_configuration $path $rootfs $name $arch $release
if [ $? -ne 0 ]; then
echo "failed write configuration file"
exit 1
fi
post_process $rootfs $release $trim_container $packages
if [ -n "$bindhome" ]; then
do_bindhome $rootfs $bindhome
finalize_user $bindhome
else
finalize_user $user
fi
echo ""
echo "##"
if [ -n "$bindhome" ]; then
echo "# Log in as user $bindhome"
else
echo "# The default user is '$user' with password '$password'!"
echo "# Use the 'sudo' command to run tasks as root in the container."
fi
echo "##"
echo ""

199
templates/lxc-voidlinux.in Normal file
View File

@ -0,0 +1,199 @@
#!/bin/bash
#
# template script for generating Void Linux container for LXC
#
#
# lxc: linux Container library
# Authors:
# Gregor Reitzenstein <dean4devil@paranoidlabs.org>
# Based on lxc-archlinux template by:
# Alexander Vladimirov <alexander.idkfa.vladimirov@gmail.com>
# John Lane <lxc@jelmail.com>
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# Utility functions
# Check if array $2 contains item $1
containsElement() {
local e
for e in "${@:2}"; do [[ "$1" == "$e" ]] && return 0; done
return 1
}
# split comma-separated string into an array
# ${1} - string to split
# ${2} - separator (default is ",")
# ${result} - result value on success
split_string() {
local ifs=${IFS}
IFS="${2:-,}"
read -ra result < <(echo "${1}")
IFS=${ifs}
return 0
}
# Make sure the usual locations are in PATH
export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
# defaults
default_path="/var/lib/lxc"
default_path="@LXCPATH@"
shared_config="@LXCTEMPLATECONFIG@/voidlinux.common.conf"
userns_config="@LXCTEMPLATECONFIG@/voidlinux.userns.conf"
pkg_blacklist=("linux>=0" "e2fsprogs>=0" "btrfs-progs>=0" "xfsprogs>=0" "f2fs-tools>=0" "dosfstools>=0")
base_packages=()
for pkg in $(xbps-query -Mv --repository="http://repo2.voidlinux.eu/current/" -x base-system); do
containsElement "$pkg" "${pkg_blacklist[@]}" || base_packages+=($pkg)
done
declare -a additional_packages
copy_configuration() {
mkdir -p "${config_path}"
local config="${config_path}/config"
echo "lxc.uts.name = ${name}" >> "${config}"
grep -q "^lxc.rootfs.path" "${config}" 2>/dev/null \
|| echo "lxc.rootfs.path = ${rootfs_path}" >> "${config}"
# Detect if were in a UserNS and include the right config
if [ -z "${LXC_MAPPED_GID+x}" ] || [ -z "${LXC_MAPPED_UID+x}" ]; then
echo "lxc.include = ${userns_config}" >> "${config}"
else
echo "lxc.include = ${shared_config}" >> "${config}"
fi
if [ $? -ne 0 ]; then
echo "Failed to configure container"
return 1
fi
return 0
}
install_void() {
if ! yes | xbps-install -Sy -R http://repo2.voidlinux.eu/current -r "${rootfs_path}" "${base_packages[@]}"
then
echo "Failed to install container packages"
return 1
fi
}
usage() {
cat <<EOF
usage:
${1} -n|--name=<container_name> [-p|--path=<path>] [-a|--arch=<arch of the container>]
[-r|--root_password=<root password>] [-P|--packages=<pkg1,pkg2,...>] [-h|--help]
Mandatory args:
-n,--name container name, used to as an identifier for that container from now on
Optional args:
-p,--path path to where the container rootfs will be created (${default_path})
--rootfs path for actual container rootfs, (${default_path}/rootfs)
-P,--packages preinstall additional packages, comma-separated list
-c,--config use specified pacman config when installing container packages
-a,--arch use specified architecture instead of host's architecture
-r,--root_password set container root password
-h,--help print this help
EOF
return 0
}
options=$(getopt -o hp:P:n:c:r: -l help,rootfs:,path:,packages:,name:,config:,root_password:,mapped-uid:,mapped-gid: -- "${@}")
if [ ${?} -ne 0 ]; then
usage "$(basename "${0}")"
exit 1
fi
eval set -- "${options}"
while true
do
case "${1}" in
-h|--help) usage "${0}" && exit 0;;
-p|--path) path=${2}; shift 2;;
-n|--name) name=${2}; shift 2;;
-c|--config) config_path=${2}; shift 2;;
--rootfs) rootfs_path=${2}; shift 2;;
-P|--packages) additional_packages=${2}; shift 2;;
-r|--root_password) root_passwd=${2}; shift 2;;
--mapped-uid) LXC_MAPPED_UID=$2; shift 2;;
--mapped-gid) LXC_MAPPED_GID=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
done
if [ -z "${name}" ]; then
echo "missing required 'name' parameter"
exit 1
fi
type xbps-install >/dev/null 2>&1
if [ ${?} -ne 0 ]; then
echo "'xbps-install' command is missing."
fi
type xbps-query >/dev/null 2>&1
if [ ${?} -ne 0 ]; then
echo "'xbps-query' command is missing."
fi
if [ -z "${rootfs_path}" ]; then
rootfs_path="${path}/rootfs"
fi
config_path="${path}"
revert() {
echo "Interrupted, cleaning up"
lxc-destroy -n "${name}"
rm -rf "${path:?}/${name}"
rm -rf "${default_path:?}/${name}"
exit 1
}
trap revert SIGHUP SIGINT SIGTERM
copy_configuration
if [ $? -ne 0 ]; then
echo "Failed to write configuration file"
rm -rf "${config_path}"
exit 1
fi
if [ ${#additional_packages[@]} -gt 0 ]; then
split_string "${additional_packages}"
base_packages+=(${result[@]})
fi
mkdir -p "${rootfs_path}"
install_void
if [ ${?} -ne 0 ]; then
echo "Failed to install Void Linux"
rm -rf "${config_path}" "${path}"
exit 1
fi
if [ -n "${root_passwd}" ]; then
echo "root:${root_passwd}" | chroot "${rootfs_path}" chpasswd
fi
cat << EOF
Void Linux Container ${name} has been successfully created. The configuration is
stored in ${config_path}/config. Please refer to https://wiki.voidlinux.eu for
information regarding Void Linux.
EOF