mirror of
https://github.com/lxc/lua-lxc.git
synced 2026-02-05 09:48:22 +01:00
initial commit
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
0
CONTRIBUTING
Normal file
0
CONTRIBUTING
Normal file
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.
|
||||
|
||||
0
MAINTAINERS
Normal file
0
MAINTAINERS
Normal file
21
Makefile.am
Normal file
21
Makefile.am
Normal file
@@ -0,0 +1,21 @@
|
||||
# Makefile.am
|
||||
|
||||
ACLOCAL_AMFLAGS = -I config
|
||||
|
||||
LIBTOOL_DEPS = @LIBTOOL_DEPS@
|
||||
SUBDIRS = src
|
||||
DIST_SUBDIRS = src
|
||||
EXTRA_DIST = \
|
||||
autogen.sh \
|
||||
CONTRIBUTING \
|
||||
MAINTAINERS
|
||||
|
||||
libtool: $(LIBTOOL_DEPS)
|
||||
$(SHELL) ./config.status libtool
|
||||
|
||||
install-data-local:
|
||||
$(MKDIR_P) $(DESTDIR)$(LXCPATH)
|
||||
$(MKDIR_P) $(DESTDIR)$(localstatedir)/cache/lxc
|
||||
|
||||
ChangeLog::
|
||||
@touch ChangeLog
|
||||
4
README.md
Normal file
4
README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# lua-lxc
|
||||
|
||||
This repository provides lua bindings for the [LXC](https://github.com/lxc/lxc)
|
||||
container API.
|
||||
31
autogen.sh
Executable file
31
autogen.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/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
|
||||
libtoolize || exit 1
|
||||
aclocal -I config || exit 1
|
||||
autoheader || exit 1
|
||||
autoconf || exit 1
|
||||
automake --add-missing --copy || exit 1
|
||||
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
|
||||
127
configure.ac
Normal file
127
configure.ac
Normal file
@@ -0,0 +1,127 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT([lua-lxc], [lxc_version])
|
||||
|
||||
# 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
|
||||
|
||||
# libtool
|
||||
LT_INIT
|
||||
AC_SUBST([LIBTOOL_DEPS])
|
||||
|
||||
AC_ARG_ENABLE([werror],
|
||||
[AC_HELP_STRING([--disable-werror],
|
||||
[do not treat warnings as errors])],
|
||||
[], [enable_werror=yes])
|
||||
|
||||
# Configuration examples
|
||||
AC_ARG_ENABLE([examples],
|
||||
[AC_HELP_STRING([--enable-examples], [install examples [default=yes]])],
|
||||
[], [enable_examples=yes])
|
||||
AM_CONDITIONAL([ENABLE_EXAMPLES], [test "x$enable_examples" = "xyes"])
|
||||
|
||||
# Lua module and scripts
|
||||
AC_ARG_WITH([lua-pc],
|
||||
[AS_HELP_STRING(
|
||||
[--with-lua-pc=PKG],
|
||||
[Specify pkg-config package name for lua]
|
||||
)], [], [with_lua_pc=no])
|
||||
|
||||
if test "x$with_lua_pc" != "xno"; then
|
||||
# exit with error if not found
|
||||
PKG_CHECK_MODULES([LUA], [$with_lua_pc], [LUAPKGCONFIG=$with_lua_pc])
|
||||
fi
|
||||
|
||||
if "x$with_lua_pc" != "xno"; then
|
||||
PKG_CHECK_MODULES([LUA], [$with_lua_pc],
|
||||
[LUAPKGCONFIG=$with_lua_pc
|
||||
enable_lua=yes],
|
||||
[enable_lua=no])
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES([LUA], [lua], [LUAPKGCONFIG=lua],
|
||||
[PKG_CHECK_MODULES([LUA], [lua5.2], [LUAPKGCONFIG=lua5.2],
|
||||
[PKG_CHECK_MODULES([LUA], [lua5.1], [LUAPKGCONFIG=lua5.1],
|
||||
[AS_IF([test "x$enable_lua" = "xyes"],
|
||||
[AC_MSG_ERROR([Lua not found. Please use --with-lua-pc=PKG])],
|
||||
[enable_lua=no])]
|
||||
)]
|
||||
)])
|
||||
|
||||
AC_MSG_CHECKING([Lua version])
|
||||
PKG_CHECK_VAR([LUA_VERSION], [$LUAPKGCONFIG], [V],,
|
||||
[PKG_CHECK_VAR([LUA_VERSION], [$LUAPKGCONFIG], [major_version])])
|
||||
AC_MSG_RESULT([$LUA_VERSION])
|
||||
AC_SUBST([LUA_LIBDIR], [$libdir/lua/$LUA_VERSION])
|
||||
AC_SUBST([LUA_SHAREDIR], [$datadir/lua/$LUA_VERSION])
|
||||
|
||||
# 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
|
||||
])
|
||||
|
||||
# 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(LXCPATH, "$with_config_path")
|
||||
|
||||
# We need the install path so criu knows where to reference the hook scripts.
|
||||
AC_DEFINE_UNQUOTED([DATADIR], "$DATADIR", ["Prefix for shared files."])
|
||||
|
||||
# Check for some standard binaries
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_PROG_SED
|
||||
|
||||
if test "x$GCC" = "xyes"; then
|
||||
CFLAGS="$CFLAGS -Wall"
|
||||
if test "x$enable_werror" = "xyes"; then
|
||||
CFLAGS="$CFLAGS -Werror"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Files requiring some variable expansion
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
src/Makefile
|
||||
])
|
||||
AC_CONFIG_COMMANDS([default],[[]],[[]])
|
||||
AC_OUTPUT
|
||||
|
||||
# Configuration overview
|
||||
cat << EOF
|
||||
|
||||
----------------------------
|
||||
Environment:
|
||||
- compiler: $CC
|
||||
- with_lua_pc: $with_lua_pc
|
||||
|
||||
EOF
|
||||
36
src/Makefile.am
Normal file
36
src/Makefile.am
Normal file
@@ -0,0 +1,36 @@
|
||||
luasharedir=$(LUA_SHAREDIR)
|
||||
lualibdir=$(LUA_LIBDIR)
|
||||
luadir=$(luasharedir)
|
||||
sodir=$(lualibdir)/lxc
|
||||
|
||||
lua_DATA=lxc.lua
|
||||
|
||||
lib_LTLIBRARIES = libcore.la
|
||||
libcore_la_SOURCES = core.c
|
||||
|
||||
AM_LDFLAGS = -Wl,-E
|
||||
|
||||
AM_CFLAGS=-I$(top_builddir)/src -I$(top_srcdir)/src $(LUA_CFLAGS) -DVERSION=\"$(VERSION)\" -DLXCPATH=\"$(LXCPATH)\"
|
||||
|
||||
libcore_la_CFLAGS = -fPIC -DPIC $(AM_CFLAGS)
|
||||
|
||||
libcore_la_LDFLAGS = \
|
||||
-shared \
|
||||
-L$(top_builddir)/ \
|
||||
-Wl,-soname,core.so.$(firstword $(subst ., ,$(VERSION)))
|
||||
|
||||
libcore_la_LIBADD = -llxc
|
||||
|
||||
install-exec-local: install-libLTLIBRARIES
|
||||
mkdir -p $(DESTDIR)$(lualibdir)/lxc/
|
||||
mv $(DESTDIR)$(libdir)/libcore.so.0.0.0 $(DESTDIR)$(lualibdir)/lxc/core.so
|
||||
rm $(DESTDIR)$(libdir)/libcore.*
|
||||
|
||||
uninstall-local:
|
||||
$(RM) $(DESTDIR)$(lualibdir)/lxc/core.so*
|
||||
|
||||
lxc.lua:
|
||||
|
||||
EXTRA_DIST= \
|
||||
lxc.lua \
|
||||
test/apitest.lua
|
||||
619
src/core.c
Normal file
619
src/core.c
Normal file
@@ -0,0 +1,619 @@
|
||||
/*
|
||||
* lua-lxc: lua bindings for lxc
|
||||
*
|
||||
* Copyright © 2012 Oracle.
|
||||
*
|
||||
* Authors:
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define LUA_LIB
|
||||
#define _GNU_SOURCE
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
#if LUA_VERSION_NUM < 502
|
||||
#define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l))
|
||||
#define luaL_setfuncs(L,l,n) (assert(n==0), luaL_register(L,NULL,l))
|
||||
#define luaL_checkunsigned(L,n) luaL_checknumber(L,n)
|
||||
#endif
|
||||
|
||||
#if LUA_VERSION_NUM >= 503
|
||||
#ifndef luaL_checkunsigned
|
||||
#define luaL_checkunsigned(L,n) ((lua_Unsigned)luaL_checkinteger(L,n))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef NO_CHECK_UDATA
|
||||
#define checkudata(L,i,tname) lua_touserdata(L, i)
|
||||
#else
|
||||
#define checkudata(L,i,tname) luaL_checkudata(L, i, tname)
|
||||
#endif
|
||||
|
||||
#define lua_boxpointer(L,u) \
|
||||
(*(void **) (lua_newuserdata(L, sizeof(void *))) = (u))
|
||||
|
||||
#define lua_unboxpointer(L,i,tname) \
|
||||
(*(void **) (checkudata(L, i, tname)))
|
||||
|
||||
#define CONTAINER_TYPENAME "lxc.container"
|
||||
|
||||
/* Max Lua arguments for function */
|
||||
#define MAXVARS 200
|
||||
|
||||
static int container_new(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c;
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
const char *configpath = NULL;
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc > 1)
|
||||
configpath = luaL_checkstring(L, 2);
|
||||
|
||||
c = lxc_container_new(name, configpath);
|
||||
if (c) {
|
||||
lua_boxpointer(L, c);
|
||||
luaL_getmetatable(L, CONTAINER_TYPENAME);
|
||||
lua_setmetatable(L, -2);
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_gc(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
|
||||
/* XXX what to do if this fails? */
|
||||
lxc_container_put(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int container_config_file_name(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
char *config_file_name;
|
||||
|
||||
config_file_name = c->config_file_name(c);
|
||||
lua_pushstring(L, config_file_name);
|
||||
free(config_file_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_defined(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
|
||||
lua_pushboolean(L, !!c->is_defined(c));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_name(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
|
||||
lua_pushstring(L, c->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_create(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
char *template_name = strdupa(luaL_checkstring(L, 2));
|
||||
int argc = lua_gettop(L);
|
||||
char **argv;
|
||||
int i;
|
||||
|
||||
argv = alloca((argc+1) * sizeof(char *));
|
||||
for (i = 0; i < argc-2; i++)
|
||||
argv[i] = strdupa(luaL_checkstring(L, i+3));
|
||||
argv[i] = NULL;
|
||||
|
||||
lua_pushboolean(L, !!c->create(c, template_name, NULL, NULL, 0, argv));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_destroy(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
|
||||
lua_pushboolean(L, !!c->destroy(c));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* container state */
|
||||
static int container_start(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
int argc = lua_gettop(L);
|
||||
char **argv = NULL;
|
||||
int i,j;
|
||||
int useinit = 0;
|
||||
|
||||
if (argc > 1) {
|
||||
argv = alloca((argc+1) * sizeof(char *));
|
||||
for (i = 0, j = 0; i < argc-1; i++) {
|
||||
const char *arg = luaL_checkstring(L, i+2);
|
||||
|
||||
if (!strcmp(arg, "useinit"))
|
||||
useinit = 1;
|
||||
else
|
||||
argv[j++] = strdupa(arg);
|
||||
}
|
||||
argv[j] = NULL;
|
||||
}
|
||||
|
||||
c->want_daemonize(c, true);
|
||||
lua_pushboolean(L, !!c->start(c, useinit, argv));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_stop(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
|
||||
lua_pushboolean(L, !!c->stop(c));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_shutdown(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
int timeout = luaL_checkinteger(L, 2);
|
||||
|
||||
lua_pushboolean(L, !!c->shutdown(c, timeout));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_wait(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
const char *state = luaL_checkstring(L, 2);
|
||||
int timeout = luaL_checkinteger(L, 3);
|
||||
|
||||
lua_pushboolean(L, !!c->wait(c, state, timeout));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_rename(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
const char *new_name;
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
if (argc > 1) {
|
||||
new_name = luaL_checkstring(L, 2);
|
||||
lua_pushboolean(L, !!c->rename(c, new_name));
|
||||
} else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_freeze(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
|
||||
lua_pushboolean(L, !!c->freeze(c));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_unfreeze(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
|
||||
lua_pushboolean(L, !!c->unfreeze(c));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_running(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
|
||||
lua_pushboolean(L, !!c->is_running(c));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_state(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
|
||||
lua_pushstring(L, c->state(c));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_init_pid(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
|
||||
lua_pushinteger(L, c->init_pid(c));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* configuration file methods */
|
||||
static int container_load_config(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
int arg_cnt = lua_gettop(L);
|
||||
const char *alt_path = NULL;
|
||||
|
||||
if (arg_cnt > 1)
|
||||
alt_path = luaL_checkstring(L, 2);
|
||||
|
||||
lua_pushboolean(L, !!c->load_config(c, alt_path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_save_config(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
int arg_cnt = lua_gettop(L);
|
||||
const char *alt_path = NULL;
|
||||
|
||||
if (arg_cnt > 1)
|
||||
alt_path = luaL_checkstring(L, 2);
|
||||
|
||||
lua_pushboolean(L, !!c->save_config(c, alt_path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_get_config_path(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
const char *config_path;
|
||||
|
||||
config_path = c->get_config_path(c);
|
||||
lua_pushstring(L, config_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_set_config_path(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
const char *config_path = luaL_checkstring(L, 2);
|
||||
|
||||
lua_pushboolean(L, !!c->set_config_path(c, config_path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_clear_config_item(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
const char *key = luaL_checkstring(L, 2);
|
||||
|
||||
lua_pushboolean(L, !!c->clear_config_item(c, key));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_get_cgroup_item(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
const char *key = luaL_checkstring(L, 2);
|
||||
int len;
|
||||
char *value;
|
||||
|
||||
len = c->get_cgroup_item(c, key, NULL, 0);
|
||||
if (len <= 0)
|
||||
goto not_found;
|
||||
|
||||
value = alloca(sizeof(char)*len + 1);
|
||||
if (c->get_cgroup_item(c, key, value, len + 1) != len)
|
||||
goto not_found;
|
||||
|
||||
lua_pushstring(L, value);
|
||||
return 1;
|
||||
|
||||
not_found:
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_get_config_item(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
const char *key = luaL_checkstring(L, 2);
|
||||
int len;
|
||||
char *value;
|
||||
|
||||
len = c->get_config_item(c, key, NULL, 0);
|
||||
if (len <= 0)
|
||||
goto not_found;
|
||||
|
||||
value = alloca(sizeof(char)*len + 1);
|
||||
if (c->get_config_item(c, key, value, len + 1) != len)
|
||||
goto not_found;
|
||||
|
||||
lua_pushstring(L, value);
|
||||
return 1;
|
||||
|
||||
not_found:
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_set_cgroup_item(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
const char *key = luaL_checkstring(L, 2);
|
||||
const char *value = luaL_checkstring(L, 3);
|
||||
|
||||
lua_pushboolean(L, !!c->set_cgroup_item(c, key, value));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_set_config_item(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
const char *key = luaL_checkstring(L, 2);
|
||||
const char *value = luaL_checkstring(L, 3);
|
||||
|
||||
lua_pushboolean(L, !!c->set_config_item(c, key, value));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_get_keys(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
const char *key = NULL;
|
||||
int len;
|
||||
char *value;
|
||||
int arg_cnt = lua_gettop(L);
|
||||
|
||||
if (arg_cnt > 1)
|
||||
key = luaL_checkstring(L, 2);
|
||||
|
||||
len = c->get_keys(c, key, NULL, 0);
|
||||
if (len <= 0)
|
||||
goto not_found;
|
||||
|
||||
value = alloca(sizeof(char)*len + 1);
|
||||
if (c->get_keys(c, key, value, len + 1) != len)
|
||||
goto not_found;
|
||||
|
||||
lua_pushstring(L, value);
|
||||
return 1;
|
||||
|
||||
not_found:
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_attach(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
int argc = lua_gettop(L);
|
||||
char **argv = NULL;
|
||||
int i;
|
||||
|
||||
if (argc > 1) {
|
||||
argv = alloca((argc+1) * sizeof(char *));
|
||||
for (i = 0; i < argc-1; i++) {
|
||||
const char *arg = luaL_checkstring(L, i+2);
|
||||
argv[i] = strdupa(arg);
|
||||
}
|
||||
argv[i] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_pushboolean(L, !(c->attach_run_wait(c, NULL, argv[0], (const char**)argv)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int container_get_interfaces(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
char **ifaces;
|
||||
int i;
|
||||
|
||||
ifaces = c->get_interfaces(c);
|
||||
|
||||
if (!ifaces){
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; ifaces[i]; i++);
|
||||
|
||||
/* protect LUA stack form overflow */
|
||||
if (i > MAXVARS || !lua_checkstack(L, i)){
|
||||
for (i = 0; ifaces[i]; i++)
|
||||
free(ifaces[i]);
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
for (i = 0; ifaces[i]; i++){
|
||||
lua_pushstring(L, ifaces[i]);
|
||||
free(ifaces[i]);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int container_get_ips(lua_State *L)
|
||||
{
|
||||
struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
|
||||
int argc = lua_gettop(L);
|
||||
char **addresses;
|
||||
char *iface = NULL, *family = NULL;
|
||||
int i, scope = 0;
|
||||
|
||||
if (argc > 1)
|
||||
iface = (char *)luaL_checkstring(L, 2);
|
||||
if (argc > 2)
|
||||
family = (char *)luaL_checkstring(L, 3);
|
||||
if (argc > 3)
|
||||
scope = luaL_checkinteger(L, 4);
|
||||
|
||||
addresses = c->get_ips(c, iface, family, scope);
|
||||
|
||||
if (!addresses){
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; addresses[i]; i++);
|
||||
|
||||
/* protect LUA stack form overflow */
|
||||
if (i > MAXVARS || !lua_checkstack(L, i)){
|
||||
for (i = 0; addresses[i]; i++)
|
||||
free(addresses[i]);
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
for (i = 0; addresses[i]; i++){
|
||||
lua_pushstring(L, addresses[i]);
|
||||
free(addresses[i]);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static luaL_Reg lxc_container_methods[] =
|
||||
{
|
||||
{"attach", container_attach},
|
||||
{"create", container_create},
|
||||
{"defined", container_defined},
|
||||
{"destroy", container_destroy},
|
||||
{"init_pid", container_init_pid},
|
||||
{"name", container_name},
|
||||
{"running", container_running},
|
||||
{"state", container_state},
|
||||
{"freeze", container_freeze},
|
||||
{"unfreeze", container_unfreeze},
|
||||
{"start", container_start},
|
||||
{"stop", container_stop},
|
||||
{"shutdown", container_shutdown},
|
||||
{"wait", container_wait},
|
||||
{"rename", container_rename},
|
||||
|
||||
{"config_file_name", container_config_file_name},
|
||||
{"load_config", container_load_config},
|
||||
{"save_config", container_save_config},
|
||||
{"get_cgroup_item", container_get_cgroup_item},
|
||||
{"set_cgroup_item", container_set_cgroup_item},
|
||||
{"get_config_path", container_get_config_path},
|
||||
{"set_config_path", container_set_config_path},
|
||||
{"get_config_item", container_get_config_item},
|
||||
{"set_config_item", container_set_config_item},
|
||||
{"clear_config_item", container_clear_config_item},
|
||||
{"get_keys", container_get_keys},
|
||||
{"get_interfaces", container_get_interfaces},
|
||||
{"get_ips", container_get_ips},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static int lxc_version_get(lua_State *L) {
|
||||
lua_pushstring(L, VERSION);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lxc_default_config_path_get(lua_State *L) {
|
||||
const char *lxcpath = lxc_get_global_config_item("lxc.lxcpath");
|
||||
|
||||
lua_pushstring(L, lxcpath);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cmd_get_config_item(lua_State *L)
|
||||
{
|
||||
int arg_cnt = lua_gettop(L);
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
const char *key = luaL_checkstring(L, 2);
|
||||
const char *lxcpath = NULL;
|
||||
char *value;
|
||||
struct lxc_container *c;
|
||||
|
||||
if (arg_cnt > 2)
|
||||
lxcpath = luaL_checkstring(L, 3);
|
||||
|
||||
c = lxc_container_new(name, lxcpath);
|
||||
if (!c)
|
||||
goto not_found;
|
||||
|
||||
value = c->get_running_config_item(c, key);
|
||||
lxc_container_put(c);
|
||||
if (value < 0)
|
||||
goto not_found;
|
||||
|
||||
lua_pushstring(L, value);
|
||||
return 1;
|
||||
|
||||
not_found:
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* utility functions */
|
||||
static int lxc_util_usleep(lua_State *L) {
|
||||
usleep((useconds_t)luaL_checkunsigned(L, 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lxc_util_dirname(lua_State *L) {
|
||||
char *path = strdupa(luaL_checkstring(L, 1));
|
||||
lua_pushstring(L, dirname(path));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static luaL_Reg lxc_lib_methods[] = {
|
||||
{"version_get", lxc_version_get},
|
||||
{"default_config_path_get", lxc_default_config_path_get},
|
||||
{"cmd_get_config_item", cmd_get_config_item},
|
||||
{"container_new", container_new},
|
||||
{"usleep", lxc_util_usleep},
|
||||
{"dirname", lxc_util_dirname},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static int lxc_lib_uninit(lua_State *L) {
|
||||
(void) L;
|
||||
/* this is where we would fini liblxc.so if we needed to */
|
||||
return 0;
|
||||
}
|
||||
|
||||
LUALIB_API int luaopen_lxc_core(lua_State *L) {
|
||||
/* this is where we would initialize liblxc.so if we needed to */
|
||||
|
||||
luaL_newlib(L, lxc_lib_methods);
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_newtable(L); /* metatable */
|
||||
lua_pushvalue(L, -1);
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, lxc_lib_uninit);
|
||||
lua_rawset(L, -3);
|
||||
lua_setmetatable(L, -3);
|
||||
lua_rawset(L, -3);
|
||||
|
||||
luaL_newmetatable(L, CONTAINER_TYPENAME);
|
||||
luaL_setfuncs(L, lxc_container_methods, 0);
|
||||
lua_pushvalue(L, -1); /* push metatable */
|
||||
lua_pushstring(L, "__gc");
|
||||
lua_pushcfunction(L, container_gc);
|
||||
lua_settable(L, -3);
|
||||
lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
|
||||
lua_pop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
421
src/lxc.lua
Executable file
421
src/lxc.lua
Executable file
@@ -0,0 +1,421 @@
|
||||
--
|
||||
-- lua lxc module
|
||||
--
|
||||
-- Copyright © 2012 Oracle.
|
||||
--
|
||||
-- Authors:
|
||||
-- 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
|
||||
--
|
||||
|
||||
local core = require("lxc.core")
|
||||
local lfs = require("lfs")
|
||||
local table = require("table")
|
||||
local string = require("string")
|
||||
local io = require("io")
|
||||
module("lxc", package.seeall)
|
||||
|
||||
local lxc_path
|
||||
local log_level = 3
|
||||
|
||||
-- lua 5.1 compat
|
||||
if table.unpack == nil then
|
||||
table.unpack = unpack
|
||||
end
|
||||
|
||||
-- the following two functions can be useful for debugging
|
||||
function printf(...)
|
||||
local function wrapper(...) io.write(string.format(...)) end
|
||||
local status, result = pcall(wrapper, ...)
|
||||
if not status then
|
||||
error(result, 2)
|
||||
end
|
||||
end
|
||||
|
||||
function log(level, ...)
|
||||
if (log_level >= level) then
|
||||
printf(os.date("%Y-%m-%d %T "))
|
||||
printf(...)
|
||||
end
|
||||
end
|
||||
|
||||
function string:split(delim, max_cols)
|
||||
local cols = {}
|
||||
local start = 1
|
||||
local nextc
|
||||
repeat
|
||||
nextc = string.find(self, delim, start)
|
||||
if (nextc and #cols ~= max_cols - 1) then
|
||||
table.insert(cols, string.sub(self, start, nextc-1))
|
||||
start = nextc + #delim
|
||||
else
|
||||
table.insert(cols, string.sub(self, start, string.len(self)))
|
||||
nextc = nil
|
||||
end
|
||||
until nextc == nil or start > #self
|
||||
return cols
|
||||
end
|
||||
|
||||
-- container class
|
||||
container = {}
|
||||
container_mt = {}
|
||||
container_mt.__index = container
|
||||
|
||||
function container:new(lname, config)
|
||||
local lcore
|
||||
local lnetcfg = {}
|
||||
local lstats = {}
|
||||
|
||||
if lname then
|
||||
if config then
|
||||
lcore = core.container_new(lname, config)
|
||||
else
|
||||
lcore = core.container_new(lname)
|
||||
end
|
||||
end
|
||||
|
||||
return setmetatable({ctname = lname, core = lcore, netcfg = lnetcfg, stats = lstats}, container_mt)
|
||||
end
|
||||
|
||||
-- methods interfacing to core functionality
|
||||
function container:attach(what, ...)
|
||||
return self.core:attach(what, ...)
|
||||
end
|
||||
|
||||
function container:config_file_name()
|
||||
return self.core:config_file_name()
|
||||
end
|
||||
|
||||
function container:defined()
|
||||
return self.core:defined()
|
||||
end
|
||||
|
||||
function container:init_pid()
|
||||
return self.core:init_pid()
|
||||
end
|
||||
|
||||
function container:name()
|
||||
return self.core:name()
|
||||
end
|
||||
|
||||
function container:start()
|
||||
return self.core:start()
|
||||
end
|
||||
|
||||
function container:stop()
|
||||
return self.core:stop()
|
||||
end
|
||||
|
||||
function container:shutdown(timeout)
|
||||
return self.core:shutdown(timeout)
|
||||
end
|
||||
|
||||
function container:wait(state, timeout)
|
||||
return self.core:wait(state, timeout)
|
||||
end
|
||||
|
||||
function container:freeze()
|
||||
return self.core:freeze()
|
||||
end
|
||||
|
||||
function container:unfreeze()
|
||||
return self.core:unfreeze()
|
||||
end
|
||||
|
||||
function container:running()
|
||||
return self.core:running()
|
||||
end
|
||||
|
||||
function container:state()
|
||||
return self.core:state()
|
||||
end
|
||||
|
||||
function container:create(template, ...)
|
||||
return self.core:create(template, ...)
|
||||
end
|
||||
|
||||
function container:destroy()
|
||||
return self.core:destroy()
|
||||
end
|
||||
|
||||
-- return nil if name missing
|
||||
function container:rename(name)
|
||||
return self.core:rename(name)
|
||||
end
|
||||
|
||||
function container:get_config_path()
|
||||
return self.core:get_config_path()
|
||||
end
|
||||
|
||||
function container:set_config_path(path)
|
||||
return self.core:set_config_path(path)
|
||||
end
|
||||
|
||||
function container:append_config_item(key, value)
|
||||
return self.core:set_config_item(key, value)
|
||||
end
|
||||
|
||||
function container:clear_config_item(key)
|
||||
return self.core:clear_config_item(key)
|
||||
end
|
||||
|
||||
function container:get_cgroup_item(key)
|
||||
return self.core:get_cgroup_item(key)
|
||||
end
|
||||
|
||||
function container:get_config_item(key)
|
||||
local value
|
||||
local vals = {}
|
||||
|
||||
value = self.core:get_config_item(key)
|
||||
|
||||
-- check if it is a single item
|
||||
if (not value or not string.find(value, "\n")) then
|
||||
return value
|
||||
end
|
||||
|
||||
-- it must be a list type item, make a table of it
|
||||
vals = value:split("\n", 1000)
|
||||
-- make it a "mixed" table, ie both dictionary and list for ease of use
|
||||
for _,v in ipairs(vals) do
|
||||
vals[v] = true
|
||||
end
|
||||
return vals
|
||||
end
|
||||
|
||||
function container:set_cgroup_item(key, value)
|
||||
return self.core:set_cgroup_item(key, value)
|
||||
end
|
||||
|
||||
function container:set_config_item(key, value)
|
||||
return self.core:set_config_item(key, value)
|
||||
end
|
||||
|
||||
function container:get_keys(base)
|
||||
local ktab = {}
|
||||
local keys
|
||||
|
||||
if (base) then
|
||||
keys = self.core:get_keys(base)
|
||||
base = base .. "."
|
||||
else
|
||||
keys = self.core:get_keys()
|
||||
base = ""
|
||||
end
|
||||
if (keys == nil) then
|
||||
return nil
|
||||
end
|
||||
keys = keys:split("\n", 1000)
|
||||
for _,v in ipairs(keys) do
|
||||
local config_item = base .. v
|
||||
ktab[v] = self.core:get_config_item(config_item)
|
||||
end
|
||||
return ktab
|
||||
end
|
||||
|
||||
-- return nil or more args
|
||||
function container:get_interfaces()
|
||||
return self.core:get_interfaces()
|
||||
end
|
||||
|
||||
-- return nil or more args
|
||||
function container:get_ips(...)
|
||||
return self.core:get_ips(...)
|
||||
end
|
||||
|
||||
function container:load_config(alt_path)
|
||||
if (alt_path) then
|
||||
return self.core:load_config(alt_path)
|
||||
else
|
||||
return self.core:load_config()
|
||||
end
|
||||
end
|
||||
|
||||
function container:save_config(alt_path)
|
||||
if (alt_path) then
|
||||
return self.core:save_config(alt_path)
|
||||
else
|
||||
return self.core:save_config()
|
||||
end
|
||||
end
|
||||
|
||||
-- methods for stats collection from various cgroup files
|
||||
-- read integers at given coordinates from a cgroup file
|
||||
function container:stat_get_ints(item, coords)
|
||||
local lines = {}
|
||||
local result = {}
|
||||
local flines = self:get_cgroup_item(item)
|
||||
|
||||
if (flines == nil) then
|
||||
for k,c in ipairs(coords) do
|
||||
table.insert(result, 0)
|
||||
end
|
||||
else
|
||||
for line in flines:gmatch("[^\r\n]+") do
|
||||
table.insert(lines, line)
|
||||
end
|
||||
for k,c in ipairs(coords) do
|
||||
local col
|
||||
|
||||
col = lines[c[1]]:split(" ", 80)
|
||||
local val = tonumber(col[c[2]])
|
||||
table.insert(result, val)
|
||||
end
|
||||
end
|
||||
return table.unpack(result)
|
||||
end
|
||||
|
||||
-- read an integer from a cgroup file
|
||||
function container:stat_get_int(item)
|
||||
local line = self:get_cgroup_item(item)
|
||||
-- if line is nil (on an error like Operation not supported because
|
||||
-- CONFIG_MEMCG_SWAP_ENABLED isn't enabled) return 0
|
||||
return tonumber(line) or 0
|
||||
end
|
||||
|
||||
function container:stat_match_get_int(item, match, column)
|
||||
local val
|
||||
local lines = self:get_cgroup_item(item)
|
||||
|
||||
if (lines == nil) then
|
||||
return 0
|
||||
end
|
||||
|
||||
for line in lines:gmatch("[^\r\n]+") do
|
||||
if (string.find(line, match)) then
|
||||
local col
|
||||
|
||||
col = line:split(" ", 80)
|
||||
val = tonumber(col[column]) or 0
|
||||
end
|
||||
end
|
||||
|
||||
return val
|
||||
end
|
||||
|
||||
function container:stats_get(total)
|
||||
local stat = {}
|
||||
stat.mem_used = self:stat_get_int("memory.usage_in_bytes")
|
||||
stat.mem_limit = self:stat_get_int("memory.limit_in_bytes")
|
||||
stat.memsw_used = self:stat_get_int("memory.memsw.usage_in_bytes")
|
||||
stat.memsw_limit = self:stat_get_int("memory.memsw.limit_in_bytes")
|
||||
stat.kmem_used = self:stat_get_int("memory.kmem.usage_in_bytes")
|
||||
stat.kmem_limit = self:stat_get_int("memory.kmem.limit_in_bytes")
|
||||
stat.cpu_use_nanos = self:stat_get_int("cpuacct.usage")
|
||||
stat.cpu_use_user,
|
||||
stat.cpu_use_sys = self:stat_get_ints("cpuacct.stat", {{1, 2}, {2, 2}})
|
||||
stat.blkio = self:stat_match_get_int("blkio.throttle.io_service_bytes", "Total", 2)
|
||||
|
||||
if (total) then
|
||||
total.mem_used = total.mem_used + stat.mem_used
|
||||
total.mem_limit = total.mem_limit + stat.mem_limit
|
||||
total.memsw_used = total.memsw_used + stat.memsw_used
|
||||
total.memsw_limit = total.memsw_limit + stat.memsw_limit
|
||||
total.kmem_used = total.kmem_used + stat.kmem_used
|
||||
total.kmem_limit = total.kmem_limit + stat.kmem_limit
|
||||
total.cpu_use_nanos = total.cpu_use_nanos + stat.cpu_use_nanos
|
||||
total.cpu_use_user = total.cpu_use_user + stat.cpu_use_user
|
||||
total.cpu_use_sys = total.cpu_use_sys + stat.cpu_use_sys
|
||||
total.blkio = total.blkio + stat.blkio
|
||||
end
|
||||
return stat
|
||||
end
|
||||
|
||||
local M = { container = container }
|
||||
|
||||
function M.stats_clear(stat)
|
||||
stat.mem_used = 0
|
||||
stat.mem_limit = 0
|
||||
stat.memsw_used = 0
|
||||
stat.memsw_limit = 0
|
||||
stat.kmem_used = 0
|
||||
stat.kmem_limit = 0
|
||||
stat.cpu_use_nanos = 0
|
||||
stat.cpu_use_user = 0
|
||||
stat.cpu_use_sys = 0
|
||||
stat.blkio = 0
|
||||
end
|
||||
|
||||
-- return configured containers found in LXC_PATH directory
|
||||
function M.containers_configured(names_only)
|
||||
local containers = {}
|
||||
|
||||
for dir in lfs.dir(lxc_path) do
|
||||
if (dir ~= "." and dir ~= "..")
|
||||
then
|
||||
local cfgfile = lxc_path .. "/" .. dir .. "/config"
|
||||
local cfgattr = lfs.attributes(cfgfile)
|
||||
|
||||
if (cfgattr and cfgattr.mode == "file") then
|
||||
if (names_only) then
|
||||
-- note, this is a "mixed" table, ie both dictionary and list
|
||||
containers[dir] = true
|
||||
table.insert(containers, dir)
|
||||
else
|
||||
local ct = container:new(dir)
|
||||
-- note, this is a "mixed" table, ie both dictionary and list
|
||||
containers[dir] = ct
|
||||
table.insert(containers, dir)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(containers, function (a,b) return (a < b) end)
|
||||
return containers
|
||||
end
|
||||
|
||||
-- return running containers found in cgroup fs
|
||||
function M.containers_running(names_only)
|
||||
local containers = {}
|
||||
local names = M.containers_configured(true)
|
||||
|
||||
for _,name in ipairs(names) do
|
||||
local ct = container:new(name)
|
||||
if ct:running() then
|
||||
-- note, this is a "mixed" table, ie both dictionary and list
|
||||
table.insert(containers, name)
|
||||
if (names_only) then
|
||||
containers[name] = true
|
||||
ct = nil
|
||||
else
|
||||
containers[name] = ct
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(containers, function (a,b) return (a < b) end)
|
||||
return containers
|
||||
end
|
||||
|
||||
function M.version_get()
|
||||
return core.version_get()
|
||||
end
|
||||
|
||||
function M.default_config_path_get()
|
||||
return core.default_config_path_get()
|
||||
end
|
||||
|
||||
function M.cmd_get_config_item(name, item, lxcpath)
|
||||
if (lxcpath) then
|
||||
return core.cmd_get_config_item(name, item, lxcpath)
|
||||
else
|
||||
return core.cmd_get_config_item(name, item)
|
||||
end
|
||||
end
|
||||
|
||||
lxc_path = core.default_config_path_get()
|
||||
|
||||
return M
|
||||
353
src/test/apitest.lua
Executable file
353
src/test/apitest.lua
Executable file
@@ -0,0 +1,353 @@
|
||||
#!/usr/bin/env lua
|
||||
--
|
||||
-- test the lxc lua api
|
||||
--
|
||||
-- Copyright © 2012 Oracle.
|
||||
--
|
||||
-- Authors:
|
||||
-- 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 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.
|
||||
--
|
||||
|
||||
local lxc = require("lxc")
|
||||
local lfs = require("lfs")
|
||||
local getopt = require("alt_getopt")
|
||||
|
||||
local LXC_PATH = lxc.default_config_path_get()
|
||||
|
||||
local container
|
||||
local cfg_containers = {}
|
||||
local optarg = {}
|
||||
local optind = {}
|
||||
|
||||
function printf(...)
|
||||
local function wrapper(...) io.write(string.format(...)) end
|
||||
local status, result = pcall(wrapper, ...)
|
||||
if not status then
|
||||
error(result, 2)
|
||||
end
|
||||
end
|
||||
|
||||
function log(level, ...)
|
||||
if (optarg["v"] >= level) then
|
||||
printf(os.date("%Y-%m-%d %T "))
|
||||
printf(...)
|
||||
printf("\n")
|
||||
end
|
||||
end
|
||||
|
||||
function die(...)
|
||||
printf(...)
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
function test_global_info()
|
||||
local cfg_containers
|
||||
local run_containers
|
||||
|
||||
log(0, "%-20s %s", "LXC version:", lxc.version_get())
|
||||
log(0, "%-20s %s", "Container name:", optarg["n"])
|
||||
if (optarg["c"]) then
|
||||
log(0, "%-20s %s", "Creating container:", "yes")
|
||||
log(0, "%-20s %s", "With template:", optarg["t"])
|
||||
end
|
||||
log(0, "%-20s %s", "Containers path:", LXC_PATH)
|
||||
|
||||
cfg_containers = lxc.containers_configured()
|
||||
log(0, "%-20s", "Containers configured:")
|
||||
for _,v in ipairs(cfg_containers) do
|
||||
log(0, " %s", v)
|
||||
end
|
||||
|
||||
run_containers = lxc.containers_running(true)
|
||||
log(0, "%-20s", "Containers running:")
|
||||
for _,v in ipairs(run_containers) do
|
||||
log(0, " %s", v)
|
||||
end
|
||||
end
|
||||
|
||||
function test_container_new()
|
||||
container = lxc.container:new(optarg["n"])
|
||||
assert(container ~= nil)
|
||||
assert(container:config_file_name() == string.format("%s/%s/config", LXC_PATH, optarg["n"]))
|
||||
end
|
||||
|
||||
function test_container_config_path()
|
||||
local cfgcontainer
|
||||
local cfgpath = "/tmp/" .. optarg["n"]
|
||||
local cfgname = cfgpath .. "/config"
|
||||
|
||||
log(0, "Test container config path...")
|
||||
|
||||
-- create a config file in the new location from container's config
|
||||
assert(lfs.mkdir(cfgpath))
|
||||
assert(container:save_config(cfgname))
|
||||
cfgcontainer = lxc.container:new(optarg["n"], "/tmp")
|
||||
assert(cfgcontainer ~= nil)
|
||||
log(0, "cfgname:%s cfgpath:%s", cfgcontainer:config_file_name(), cfgcontainer:get_config_path())
|
||||
assert(cfgcontainer:config_file_name() == cfgname)
|
||||
assert(cfgcontainer:get_config_path() == "/tmp")
|
||||
assert(cfgcontainer:set_config_path(LXC_PATH))
|
||||
assert(cfgcontainer:get_config_path() == LXC_PATH)
|
||||
|
||||
assert(os.remove(cfgname))
|
||||
assert(lfs.rmdir(cfgpath))
|
||||
end
|
||||
|
||||
function test_container_create()
|
||||
if (optarg["c"]) then
|
||||
log(0, "%-20s %s", "Destroy existing container:", optarg["n"])
|
||||
container:destroy()
|
||||
assert(container:defined() == false)
|
||||
else
|
||||
local cfg_containers = lxc.containers_configured()
|
||||
if (cfg_containers[optarg["n"]]) then
|
||||
log(0, "%-20s %s", "Use existing container:", optarg["n"])
|
||||
return
|
||||
end
|
||||
end
|
||||
log(0, "%-20s %s", "Creating rootfs using:", optarg["t"])
|
||||
assert(container:create(optarg["t"]) == true)
|
||||
assert(container:defined() == true)
|
||||
assert(container:name() == optarg["n"])
|
||||
end
|
||||
|
||||
function test_container_started()
|
||||
local now_running
|
||||
log(2, "state:%s pid:%d\n", container:state(), container:init_pid())
|
||||
assert(container:init_pid() > 1)
|
||||
assert(container:running() == true)
|
||||
assert(container:state() == "RUNNING")
|
||||
now_running = lxc.containers_running(true)
|
||||
assert(now_running[optarg["n"]] ~= nil)
|
||||
log(1, "%-20s %s", "Running, init pid:", container:init_pid())
|
||||
end
|
||||
|
||||
function test_container_stopped()
|
||||
local now_running
|
||||
assert(container:init_pid() == -1)
|
||||
assert(container:running() == false)
|
||||
assert(container:state() == "STOPPED")
|
||||
now_running = lxc.containers_running(true)
|
||||
assert(now_running[optarg["n"]] == nil)
|
||||
end
|
||||
|
||||
function test_container_frozen()
|
||||
local now_running
|
||||
assert(container:init_pid() > 1)
|
||||
assert(container:running() == true)
|
||||
assert(container:state() == "FROZEN")
|
||||
now_running = lxc.containers_running(true)
|
||||
assert(now_running[optarg["n"]] ~= nil)
|
||||
end
|
||||
|
||||
function test_container_start()
|
||||
log(0, "Starting...")
|
||||
if (not container:start()) then
|
||||
log(1, "Start returned failure, waiting another 10 seconds...")
|
||||
container:wait("RUNNING", 10)
|
||||
end
|
||||
container:wait("RUNNING", 1)
|
||||
end
|
||||
|
||||
function test_container_stop()
|
||||
log(0, "Stopping...")
|
||||
if (not container:stop()) then
|
||||
log(1, "Stop returned failure, waiting another 10 seconds...")
|
||||
container:wait("STOPPED", 10)
|
||||
end
|
||||
container:wait("STOPPED", 1)
|
||||
end
|
||||
|
||||
function test_container_freeze()
|
||||
log(0, "Freezing...")
|
||||
if (not container:freeze()) then
|
||||
log(1, "Freeze returned failure, waiting another 10 seconds...")
|
||||
container:wait("FROZEN", 10)
|
||||
end
|
||||
end
|
||||
|
||||
function test_container_unfreeze()
|
||||
log(0, "Unfreezing...")
|
||||
if (not container:unfreeze()) then
|
||||
log(1, "Unfreeze returned failure, waiting another 10 seconds...")
|
||||
container:wait("RUNNING", 10)
|
||||
end
|
||||
end
|
||||
|
||||
function test_container_shutdown()
|
||||
log(0, "Shutting down...")
|
||||
container:shutdown(5)
|
||||
|
||||
if (container:running()) then
|
||||
test_container_stop()
|
||||
end
|
||||
end
|
||||
|
||||
function test_container_in_cfglist(should_find)
|
||||
local cfg_containers = lxc.containers_configured()
|
||||
|
||||
if (should_find) then
|
||||
assert(cfg_containers[container:name()] ~= nil)
|
||||
else
|
||||
assert(cfg_containers[container:name()] == nil)
|
||||
end
|
||||
end
|
||||
|
||||
function test_container_attach()
|
||||
log(0, "Test attach...")
|
||||
assert(container:running() == true)
|
||||
assert(container:attach("/bin/ps") == true)
|
||||
end
|
||||
|
||||
function test_container_cgroup()
|
||||
log(0, "Test get/set cgroup items...")
|
||||
|
||||
max_mem = container:get_cgroup_item("memory.max_usage_in_bytes")
|
||||
saved_limit = container:get_cgroup_item("memory.limit_in_bytes")
|
||||
assert(saved_limit ~= max_mem)
|
||||
assert(container:set_cgroup_item("memory.limit_in_bytes", max_mem))
|
||||
assert(container:get_cgroup_item("memory.limit_in_bytes") ~= saved_limit)
|
||||
assert(container:set_cgroup_item("memory.limit_in_bytes", "-1"))
|
||||
end
|
||||
|
||||
function test_container_cmd()
|
||||
log(0, "Test get config from running container...")
|
||||
veth_pair = lxc.cmd_get_config_item(optarg["n"], "lxc.net.0.veth.pair")
|
||||
log(0, " veth.pair:%s", veth_pair)
|
||||
end
|
||||
|
||||
function test_config_items()
|
||||
log(0, "Test set/clear configuration items...")
|
||||
|
||||
-- test setting a 'single type' item
|
||||
assert(container:get_config_item("lxc.uts.name") == optarg["n"])
|
||||
container:set_config_item("lxc.uts.name", "foobar")
|
||||
assert(container:get_config_item("lxc.uts.name") == "foobar")
|
||||
container:set_config_item("lxc.uts.name", optarg["n"])
|
||||
assert(container:get_config_item("lxc.uts.name") == optarg["n"])
|
||||
|
||||
-- test clearing/setting a 'list type' item
|
||||
container:clear_config_item("lxc.cap.drop")
|
||||
container:set_config_item("lxc.cap.drop", "new_cap1")
|
||||
container:set_config_item("lxc.cap.drop", "new_cap2")
|
||||
local cap_drop = container:get_config_item("lxc.cap.drop")
|
||||
assert(cap_drop["new_cap1"] ~= nil)
|
||||
assert(cap_drop["new_cap2"] ~= nil)
|
||||
-- note: clear_config_item only works on list type items
|
||||
container:clear_config_item("lxc.cap.drop")
|
||||
assert(container:get_config_item("lxc.cap.drop") == nil)
|
||||
|
||||
local altname = "/tmp/" .. optarg["n"] .. ".altconfig"
|
||||
log(0, "Test saving to an alternate (%s) config file...", altname)
|
||||
assert(container:save_config(altname))
|
||||
assert(os.remove(altname))
|
||||
end
|
||||
|
||||
function test_config_mount_entries()
|
||||
local mntents
|
||||
|
||||
-- mount entries are a list type item
|
||||
mntents = container:get_config_item("lxc.mount.entry")
|
||||
log(0, "Mount entries:")
|
||||
for _,v in ipairs(mntents) do
|
||||
log(0, " %s", v)
|
||||
end
|
||||
end
|
||||
|
||||
function test_config_keys()
|
||||
local keys
|
||||
|
||||
keys = container:get_keys()
|
||||
log(0, "Top level keys:")
|
||||
for k,v in pairs(keys) do
|
||||
log(0, " %s = %s", k, v or "")
|
||||
end
|
||||
end
|
||||
|
||||
function test_config_network(net_nr)
|
||||
log(0, "Test network %d config...", net_nr)
|
||||
local netcfg
|
||||
|
||||
netcfg = container:get_keys("lxc.net." .. net_nr)
|
||||
if (netcfg == nil) then
|
||||
return
|
||||
end
|
||||
for k,v in pairs(netcfg) do
|
||||
log(0, " %s = %s", k, v or "")
|
||||
end
|
||||
assert(netcfg["flags"] == "up")
|
||||
assert(container:get_config_item("lxc.net."..net_nr..".type") == "veth")
|
||||
end
|
||||
|
||||
|
||||
function usage()
|
||||
die("Usage: apitest <options>\n" ..
|
||||
" -v|--verbose increase verbosity with each -v\n" ..
|
||||
" -h|--help print help message\n" ..
|
||||
" -n|--name name of container to use for testing\n" ..
|
||||
" -c|--create create the test container anew\n" ..
|
||||
" -l|--login do interactive login test\n" ..
|
||||
" -t|--template template to use when creating test container\n"
|
||||
)
|
||||
end
|
||||
|
||||
local long_opts = {
|
||||
verbose = "v",
|
||||
help = "h",
|
||||
name = "n",
|
||||
create = "c",
|
||||
template = "t",
|
||||
}
|
||||
|
||||
optarg,optind = alt_getopt.get_opts (arg, "hvn:ct:", long_opts)
|
||||
optarg["v"] = tonumber(optarg["v"]) or 0
|
||||
optarg["n"] = optarg["n"] or "lua-apitest"
|
||||
optarg["c"] = optarg["c"] or nil
|
||||
optarg["t"] = optarg["t"] or "busybox"
|
||||
if (optarg["h"] ~= nil) then
|
||||
usage()
|
||||
end
|
||||
|
||||
test_global_info()
|
||||
test_container_new()
|
||||
test_container_create()
|
||||
test_container_stopped()
|
||||
test_container_in_cfglist(true)
|
||||
test_container_config_path()
|
||||
|
||||
test_config_items()
|
||||
test_config_keys()
|
||||
test_config_mount_entries()
|
||||
test_config_network(0)
|
||||
|
||||
test_container_start()
|
||||
test_container_started()
|
||||
|
||||
test_container_attach()
|
||||
test_container_cgroup()
|
||||
test_container_cmd()
|
||||
|
||||
test_container_freeze()
|
||||
test_container_frozen()
|
||||
test_container_unfreeze()
|
||||
test_container_started()
|
||||
|
||||
test_container_shutdown()
|
||||
test_container_stopped()
|
||||
container:destroy()
|
||||
test_container_in_cfglist(false)
|
||||
|
||||
log(0, "All tests passed")
|
||||
Reference in New Issue
Block a user