forked from neil/lxc-templates
initial commit
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
commit
711ed73634
107
CONTRIBUTING
Normal file
107
CONTRIBUTING
Normal 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
502
COPYING
Normal 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
239
INSTALL
Normal 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
12
MAINTAINERS
Normal 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
18
Makefile.am
Normal 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
|
29
autogen.sh
Executable file
29
autogen.sh
Executable 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
37
config/Makefile.am
Normal 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
137
config/acinclude.m4
Normal 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
|
24
config/alpine.common.conf.in
Normal file
24
config/alpine.common.conf.in
Normal 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
|
2
config/alpine.userns.conf.in
Normal file
2
config/alpine.userns.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the global userns config.
|
||||
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
|
31
config/archlinux.common.conf.in
Normal file
31
config/archlinux.common.conf.in
Normal 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
|
2
config/archlinux.userns.conf.in
Normal file
2
config/archlinux.userns.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the global userns config
|
||||
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
|
20
config/centos.common.conf.in
Normal file
20
config/centos.common.conf.in
Normal 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
|
2
config/centos.userns.conf.in
Normal file
2
config/centos.userns.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the global userns config
|
||||
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
|
28
config/debian.common.conf.in
Normal file
28
config/debian.common.conf.in
Normal 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
|
2
config/debian.userns.conf.in
Normal file
2
config/debian.userns.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the global userns config
|
||||
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
|
21
config/fedora.common.conf.in
Normal file
21
config/fedora.common.conf.in
Normal 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
|
2
config/fedora.userns.conf.in
Normal file
2
config/fedora.userns.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the global userns config
|
||||
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
|
27
config/gentoo.common.conf.in
Normal file
27
config/gentoo.common.conf.in
Normal 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
|
45
config/gentoo.moresecure.conf.in
Normal file
45
config/gentoo.moresecure.conf.in
Normal 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.
|
2
config/gentoo.userns.conf.in
Normal file
2
config/gentoo.userns.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the global userns config
|
||||
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
|
22
config/opensuse.common.conf.in
Normal file
22
config/opensuse.common.conf.in
Normal 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
|
2
config/opensuse.userns.conf.in
Normal file
2
config/opensuse.userns.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the global userns config
|
||||
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
|
50
config/openwrt.common.conf.in
Normal file
50
config/openwrt.common.conf.in
Normal 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
|
20
config/oracle.common.conf.in
Normal file
20
config/oracle.common.conf.in
Normal 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
|
2
config/oracle.userns.conf.in
Normal file
2
config/oracle.userns.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the global userns config
|
||||
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
|
9
config/plamo.common.conf.in
Normal file
9
config/plamo.common.conf.in
Normal 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
|
2
config/plamo.userns.conf.in
Normal file
2
config/plamo.userns.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the global userns config
|
||||
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
|
79
config/sabayon.common.conf.in
Normal file
79
config/sabayon.common.conf.in
Normal 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/
|
2
config/sabayon.userns.conf.in
Normal file
2
config/sabayon.userns.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the global userns config
|
||||
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
|
46
config/slackware.common.conf.in
Normal file
46
config/slackware.common.conf.in
Normal 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
|
2
config/slackware.userns.conf.in
Normal file
2
config/slackware.userns.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the global userns config
|
||||
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
|
20
config/sparclinux.common.conf.in
Normal file
20
config/sparclinux.common.conf.in
Normal 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
|
2
config/sparclinux.userns.conf.in
Normal file
2
config/sparclinux.userns.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the global userns config
|
||||
lxc.include = @LXCTEMPLATECONFIG@/userns.conf
|
4
config/ubuntu-cloud.common.conf.in
Normal file
4
config/ubuntu-cloud.common.conf.in
Normal 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
|
2
config/ubuntu-cloud.lucid.conf.in
Normal file
2
config/ubuntu-cloud.lucid.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the main Ubuntu lucid config
|
||||
lxc.include = @LXCTEMPLATECONFIG@/ubuntu.lucid.conf
|
2
config/ubuntu-cloud.userns.conf.in
Normal file
2
config/ubuntu-cloud.userns.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# This derives from the main Ubuntu userns config
|
||||
lxc.include = @LXCTEMPLATECONFIG@/ubuntu.userns.conf
|
35
config/ubuntu.common.conf.in
Normal file
35
config/ubuntu.common.conf.in
Normal 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
|
2
config/ubuntu.lucid.conf.in
Normal file
2
config/ubuntu.lucid.conf.in
Normal file
@ -0,0 +1,2 @@
|
||||
# Ubuntu 10.04 LTS doesn't have /dev/lxc/
|
||||
lxc.tty.dir =
|
6
config/ubuntu.userns.conf.in
Normal file
6
config/ubuntu.userns.conf.in
Normal 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
|
35
config/voidlinux.common.conf.in
Normal file
35
config/voidlinux.common.conf.in
Normal 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
|
8
config/voidlinux.userns.conf.in
Normal file
8
config/voidlinux.userns.conf.in
Normal 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
222
configure.ac
Normal 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
25
templates/Makefile.am
Normal 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
516
templates/lxc-alpine.in
Normal 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
498
templates/lxc-altlinux.in
Normal 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
334
templates/lxc-archlinux.in
Normal 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
484
templates/lxc-busybox.in
Normal 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
968
templates/lxc-centos.in
Normal 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
343
templates/lxc-cirros.in
Normal 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
824
templates/lxc-debian.in
Normal 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
|
1495
templates/lxc-fedora-legacy.in
Normal file
1495
templates/lxc-fedora-legacy.in
Normal file
File diff suppressed because it is too large
Load Diff
1291
templates/lxc-fedora.in
Normal file
1291
templates/lxc-fedora.in
Normal file
File diff suppressed because it is too large
Load Diff
833
templates/lxc-gentoo.in
Normal file
833
templates/lxc-gentoo.in
Normal 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
|
484
templates/lxc-openmandriva.in
Normal file
484
templates/lxc-openmandriva.in
Normal 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
557
templates/lxc-opensuse.in
Normal 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
972
templates/lxc-oracle.in
Normal 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
384
templates/lxc-plamo.in
Normal 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
484
templates/lxc-pld.in
Normal 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
513
templates/lxc-sabayon.in
Normal 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
793
templates/lxc-slackware.in
Normal 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
702
templates/lxc-sparclinux.in
Normal 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
276
templates/lxc-sshd.in
Normal 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
|
374
templates/lxc-ubuntu-cloud.in
Normal file
374
templates/lxc-ubuntu-cloud.in
Normal 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
877
templates/lxc-ubuntu.in
Normal 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
199
templates/lxc-voidlinux.in
Normal 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
|
Loading…
Reference in New Issue
Block a user