diff options
Diffstat (limited to 'puppet/modules')
38 files changed, 2772 insertions, 0 deletions
| diff --git a/puppet/modules/backupninja/.gitrepo b/puppet/modules/backupninja/.gitrepo new file mode 100644 index 00000000..ea7862f0 --- /dev/null +++ b/puppet/modules/backupninja/.gitrepo @@ -0,0 +1,11 @@ +; DO NOT EDIT (unless you know what you are doing) +; +; This subdirectory is a git "subrepo", and this file is maintained by the +; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme +; +[subrepo] +	remote = https://leap.se/git/puppet_backupninja +	branch = master +	commit = 5268a87c329f895017f8ea6c6abc377a4f9a6a77 +	parent = 1e1e25286b64790141c9627f81b50f579b13b719 +	cmdver = 0.3.0 diff --git a/puppet/modules/backupninja/LICENSE b/puppet/modules/backupninja/LICENSE new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/puppet/modules/backupninja/LICENSE @@ -0,0 +1,674 @@ +                    GNU GENERAL PUBLIC LICENSE +                       Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +                            Preamble + +  The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +  The licenses for most software and other practical works are designed +to take away your freedom to share and change the works.  By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users.  We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors.  You can apply it to +your programs, too. + +  When we speak of free software, we are referring to freedom, 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 +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +  To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights.  Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + +  For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received.  You must make sure that they, too, receive +or can get the source code.  And you must show them these terms so they +know their rights. + +  Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +  For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software.  For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +  Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so.  This is fundamentally incompatible with the aim of +protecting users' freedom to change the software.  The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable.  Therefore, we +have designed this version of the GPL to prohibit the practice for those +products.  If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + +  Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary.  To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + +  The precise terms and conditions for copying, distribution and +modification follow. + +                       TERMS AND CONDITIONS + +  0. Definitions. + +  "This License" refers to version 3 of the GNU General Public License. + +  "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +  "The Program" refers to any copyrightable work licensed under this +License.  Each licensee is addressed as "you".  "Licensees" and +"recipients" may be individuals or organizations. + +  To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy.  The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + +  A "covered work" means either the unmodified Program or a work based +on the Program. + +  To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy.  Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +  To "convey" a work means any kind of propagation that enables other +parties to make or receive copies.  Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +  An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License.  If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +  1. Source Code. + +  The "source code" for a work means the preferred form of the work +for making modifications to it.  "Object code" means any non-source +form of a work. + +  A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +  The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form.  A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +  The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities.  However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work.  For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +  The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +  The Corresponding Source for a work in source code form is that +same work. + +  2. Basic Permissions. + +  All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met.  This License explicitly affirms your unlimited +permission to run the unmodified Program.  The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work.  This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +  You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force.  You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright.  Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +  Conveying under any other circumstances is permitted solely under +the conditions stated below.  Sublicensing is not allowed; section 10 +makes it unnecessary. + +  3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +  No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +  When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +  4. Conveying Verbatim Copies. + +  You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +  You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +  5. Conveying Modified Source Versions. + +  You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + +    a) The work must carry prominent notices stating that you modified +    it, and giving a relevant date. + +    b) The work must carry prominent notices stating that it is +    released under this License and any conditions added under section +    7.  This requirement modifies the requirement in section 4 to +    "keep intact all notices". + +    c) You must license the entire work, as a whole, under this +    License to anyone who comes into possession of a copy.  This +    License will therefore apply, along with any applicable section 7 +    additional terms, to the whole of the work, and all its parts, +    regardless of how they are packaged.  This License gives no +    permission to license the work in any other way, but it does not +    invalidate such permission if you have separately received it. + +    d) If the work has interactive user interfaces, each must display +    Appropriate Legal Notices; however, if the Program has interactive +    interfaces that do not display Appropriate Legal Notices, your +    work need not make them do so. + +  A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit.  Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +  6. Conveying Non-Source Forms. + +  You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + +    a) Convey the object code in, or embodied in, a physical product +    (including a physical distribution medium), accompanied by the +    Corresponding Source fixed on a durable physical medium +    customarily used for software interchange. + +    b) Convey the object code in, or embodied in, a physical product +    (including a physical distribution medium), accompanied by a +    written offer, valid for at least three years and valid for as +    long as you offer spare parts or customer support for that product +    model, to give anyone who possesses the object code either (1) a +    copy of the Corresponding Source for all the software in the +    product that is covered by this License, on a durable physical +    medium customarily used for software interchange, for a price no +    more than your reasonable cost of physically performing this +    conveying of source, or (2) access to copy the +    Corresponding Source from a network server at no charge. + +    c) Convey individual copies of the object code with a copy of the +    written offer to provide the Corresponding Source.  This +    alternative is allowed only occasionally and noncommercially, and +    only if you received the object code with such an offer, in accord +    with subsection 6b. + +    d) Convey the object code by offering access from a designated +    place (gratis or for a charge), and offer equivalent access to the +    Corresponding Source in the same way through the same place at no +    further charge.  You need not require recipients to copy the +    Corresponding Source along with the object code.  If the place to +    copy the object code is a network server, the Corresponding Source +    may be on a different server (operated by you or a third party) +    that supports equivalent copying facilities, provided you maintain +    clear directions next to the object code saying where to find the +    Corresponding Source.  Regardless of what server hosts the +    Corresponding Source, you remain obligated to ensure that it is +    available for as long as needed to satisfy these requirements. + +    e) Convey the object code using peer-to-peer transmission, provided +    you inform other peers where the object code and Corresponding +    Source of the work are being offered to the general public at no +    charge under subsection 6d. + +  A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +  A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling.  In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage.  For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product.  A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +  "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source.  The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +  If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information.  But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +  The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed.  Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +  Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +  7. Additional Terms. + +  "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law.  If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +  When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it.  (Additional permissions may be written to require their own +removal in certain cases when you modify the work.)  You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +  Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + +    a) Disclaiming warranty or limiting liability differently from the +    terms of sections 15 and 16 of this License; or + +    b) Requiring preservation of specified reasonable legal notices or +    author attributions in that material or in the Appropriate Legal +    Notices displayed by works containing it; or + +    c) Prohibiting misrepresentation of the origin of that material, or +    requiring that modified versions of such material be marked in +    reasonable ways as different from the original version; or + +    d) Limiting the use for publicity purposes of names of licensors or +    authors of the material; or + +    e) Declining to grant rights under trademark law for use of some +    trade names, trademarks, or service marks; or + +    f) Requiring indemnification of licensors and authors of that +    material by anyone who conveys the material (or modified versions of +    it) with contractual assumptions of liability to the recipient, for +    any liability that these contractual assumptions directly impose on +    those licensors and authors. + +  All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10.  If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term.  If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +  If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +  Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +  8. Termination. + +  You may not propagate or modify a covered work except as expressly +provided under this License.  Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +  However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +  Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +  Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License.  If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +  9. Acceptance Not Required for Having Copies. + +  You are not required to accept this License in order to receive or +run a copy of the Program.  Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance.  However, +nothing other than this License grants you permission to propagate or +modify any covered work.  These actions infringe copyright if you do +not accept this License.  Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +  10. Automatic Licensing of Downstream Recipients. + +  Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License.  You are not responsible +for enforcing compliance by third parties with this License. + +  An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations.  If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +  You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License.  For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +  11. Patents. + +  A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based.  The +work thus licensed is called the contributor's "contributor version". + +  A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version.  For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +  Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +  In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement).  To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +  If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients.  "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +  If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +  A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License.  You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +  Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +  12. No Surrender of Others' Freedom. + +  If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all.  For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +  13. Use with the GNU Affero General Public License. + +  Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work.  The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +  14. Revised Versions of this License. + +  The Free Software Foundation may publish revised and/or new versions of +the GNU 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 +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation.  If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + +  If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +  Later license versions may give you additional or different +permissions.  However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +  15. Disclaimer of Warranty. + +  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM +IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +  16. Limitation of Liability. + +  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + +  17. Interpretation of Sections 15 and 16. + +  If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +                     END OF TERMS AND CONDITIONS + +            How to Apply These Terms to Your New Programs + +  If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +  To do so, attach the following notices to the program.  It is safest +to attach them to the start of each source file to most effectively +state 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 program's name and a brief idea of what it does.> +    Copyright (C) <year>  <name of author> + +    This program is free software: you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation, either version 3 of the License, or +    (at your option) any later version. + +    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, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + +  If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + +    <program>  Copyright (C) <year>  <name of author> +    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +    This is free software, and you are welcome to redistribute it +    under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License.  Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + +  You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + +  The GNU General Public License does not permit incorporating your program +into proprietary programs.  If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library.  If this is what you want to do, use the GNU Lesser General +Public License instead of this License.  But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/puppet/modules/backupninja/README b/puppet/modules/backupninja/README new file mode 100644 index 00000000..42a8bfe2 --- /dev/null +++ b/puppet/modules/backupninja/README @@ -0,0 +1,202 @@ +Backupninja Module +------------------- + +This module helps you configure all of your backups with puppet, using +backupninja! + +!! UPGRADE NOTICE !! + +If you were previously using this module, some pieces have changed, +and you need to carefully change your use of them, or you will find +your backups could stop working or get duplicated. + +The backupninja::client class has been renamed to backupninja, and is +now *required* in all node manifests. Make sure the backupninja class +is now declared in all your node manifests! This new class now defines +defaults which were previously provided by backupninja::client::defaults, +and can now be overridden thanks to the brand new technology of class +parameters. This class also manages the backupninja configuration file, +replacing the backupninja::config ressource. + +The backupninja::server class now takes parameters, replacing several +global variables such as $backupdir, $backupserver_tag and +$nagios_server. The $manage_nagios parameter also replaces the +$use_nagios global. + +As for handlers, they don't include the backupninja::client anymore and +now read several default values from the backupninja base class. The +$installkey parameter used in several handlers has been renamed to +$keymanage, to keep in line with the base class parameter. + +If you were using the rdiff-backup handler, you need to read the +following section carefully. + +Changes to the rdiff-backup handler +----------------------------------- + +You will need to make sure you change all of your "$directory" +parameters to be "$home" instead, and on your backupserver you will need +to move all of your backups into "$home"/rdiff-backup. Previously, they +were put in "$directory", which doubled as the home for the user that +was created. This caused problems with rdiff-backup because of dot files +and other things which were not part of any rdiff-backup. + +The rdiff resource name is now used as the subdirectory where rdiff +backups are sent. This was previously hardcoded to "rdiff-backup", but +in order to support multiple rdiff backups per host, we now use the +resource name. So if you were using the following resource: + +    backupninja::rdiff { 'main': } + +You will want to use the following resource: + +    backupninja::rdiff { 'rdiff-backup': } +    file { '/etc/backup.d/90_main.rdiff': ensure => absent; } + +Otherwise your backups may be duplicated! + +Changes to nagios integration +----------------------------- + +The default nagios passive service name has changed from "backups" to +"backups-${name}". If you want it to be automatically created on your +nagios host, you will need to set $backupninja::manage_nagios to true. +on the client. + +Use the following resource to remove the old "backups" passive service. + +    nagios::service { 'backups': ensure => absent } + +Getting started +--------------- + +This module requires Puppet versions 2.7 and up. + +An up-to-date version of the puppet-stdlib module is also required. + +Configure your backup server +---------------------------- + +Now you will need to configure a backup server by adding the following +to your node definition for that server: + +  include backupninja::server + +The default configuration will store backup data in the "/backup" +directory. To change this you may declare the class with a "backupdir" +parameter: + +  class { 'backupninja::server': +    backupdir => '/mnt/backupdata' +  } + +By configuring a backupninja::server, this module will automatically +create sandboxed users on the server for each client for their +backups. + +Configure your backup clients +----------------------------- + +First, you need to include the backupninja class or declare it with +custom parameters: + +  class { 'backupninja': +	loglvl => 3, +	usecolors => false, +	reportsuccess => false, +	reportwarning => true, +    ensure_backupninja_version => '1.0.1-1', +    ensure_rdiffbackup_version => '1.2.8-7' +  } + +In this case, the module will make sure that the backupninja package +is installed (using puppet's ensure parameter language) and create the +/etc/backupninja.conf configuration file. + +If you need to specify a specific version of either backupninja itself, +or the specific programs that the handler class installs, you can +specify the version you need installed by providing a class parameter, +as shown in the example. + +Configuring handlers +-------------------- + +Depending on which backup method you want to use on your client, you +can simply specify some configuration options for that handler that are +necessary for your client. + +Each handler has its own configuration options necessary to make it +work, each of those are available as puppet parameters. You can see +the handler documentation, or look at the handler puppet files +included in this module to see your different options. + +Included below are some configuration examples for different handlers. + +* An example mysql handler configuration: + +backupninja::mysql { 'all_databases': +	user => root, +	backupdir => '/var/backups', +	compress => true, +	sqldump => true +} + +* An example rdiff-backup handler configuration: + +backupninja::rdiff { 'backup_all': +	directory => '/media/backupdisk', +	include => ['/var/backups', '/home', '/var/lib/dpkg/status'], +	exclude => '/home/*/.gnupg' +} + +* A remote rdiff-backup handler: + +backupninja::rdiff { 'main': +    host => 'backup.example.com', +    type => 'remote', +    directory => "/backup/${::fqdn}", +    user => "backup-${::hostname}", +} + +Automatic creation of ssh-keys for duplicity +-------------------------------------------- + +backupninja::duplicity can be used to + +- create an ssh keypair for a client +- place the keypair on the puppetmaster in a given location +- place the keypair in /root/.ssh on the client + +i.e.: + +  backupninja::duplicity { "duplicity_${::fqdn}": +    sshoptions        => "-oIdentityFile=/root/.ssh/backupninja_${::hostname}_id_rsa", +    desthost          => 'HOST', +    destdir           => "/var/backup/backupninja/${::fqdn}", +    destuser          => "backupninja_${::hostname}", +    encryptkey        => 'KEYID', +    password          => 'PW', +    backupkeystore    => 'puppet:///keys', +    backupkeystorefspath => '/etc/puppet/modules/keys/files', +    backupkeydestname => "backupninja_${::hostname}_id_rsa", +    createkey         => true, +    installkey        => true, +    ... +  } + + +Nagios alerts about backup freshness +------------------------------------ + +If you set the $backupninja::server::nagios_server variable to be the +name of your nagios server, then a passive nagios service gets setup so +that the backup server pushes checks, via a cronjob that calls +/usr/local/bin/checkbackups.pl, to the nagios server to alert about +relative backup freshness. + +To use this feature a few pre-requisites are necessary: + + . configure nsca on your backup server (not done via puppet yet) + . configure nsca on your nagios server (not done via puppet yet) + . server backup directories are named after their $fqdn + . backups must be under $home/dup, $home/rdiff-backup depending on method diff --git a/puppet/modules/backupninja/files/checkbackups.pl b/puppet/modules/backupninja/files/checkbackups.pl new file mode 100755 index 00000000..39914469 --- /dev/null +++ b/puppet/modules/backupninja/files/checkbackups.pl @@ -0,0 +1,194 @@ +#!/usr/bin/perl -w + +# This script is designed to check a backup directory populated with +# subdirectories named after hosts, within which there are backups of various +# types. +# +# Example: +# /home/backup: +# foo.example.com +#  +# foo.example.com: +# rdiff-backup .ssh +# +# rdiff-backup: +# root home rdiff-backup-data usr var +# +# There are heuristics to determine the backup type. Currently, the following +# types are supported: +# +# rdiff-backup: assumes there is a rdiff-backup/rdiff-backup-data/backup.log file +# duplicity: assumes there is a dup subdirectory, checks the latest file +# dump files: assumes there is a dump subdirectory, checks the latest file +# +# This script returns output suitable for send_nsca to send the results to +# nagios and should therefore be used like this: +# +# checkbackups.sh | send_nsca -H nagios.example.com + +use Getopt::Std; + +# XXX: taken from utils.sh from nagios-plugins-basic +my $STATE_OK=0; +my $STATE_WARNING=1; +my $STATE_CRITICAL=2; +my $STATE_UNKNOWN=3; +my $STATE_DEPENDENT=4; +my %ERRORS=(0=>'OK',1=>'WARNING',2=>'CRITICAL',3=>'UNKNOWN',4=>'DEPENDENT'); + +# gross hack: we look into subdirs to find vservers +my @vserver_dirs = qw{/var/lib/vservers /vservers}; + +our $opt_d = "/backup"; +our $opt_c = 48 * 60 * 60; +our $opt_w = 24 * 60 * 60; +our $opt_v = 0; +our $opt_o; +our $opt_s; + +if (!getopts('d:c:w:s:vo')) { +	print <<EOF +Usage: $0 [ -d <backupdir> ] [ -c <threshold> ] [ -w <threshold> ] [ -o ] [ -s <host> ] [ -v ] +EOF +	; +	exit(); +} + +sub check_rdiff { +    my ($host, $dir, $optv) = @_; +    my $flag="$dir/rdiff-backup-data/backup.log"; +    my $extra_msg = ''; +    my @vservers; +    if (open(FLAG, $flag)) { +        while (<FLAG>) { +            if (/EndTime ([0-9]*).[0-9]* \((.*)\)/) { +                $last_bak = $1; +                $extra_msg = ' [backup.log]'; +                $opt_v && print STDERR "found timestamp $1 ($2) in $flag\n"; +            } +        } +        if (!$last_bak) { +            print_status($host, $STATE_UNKNOWN, "cannot parse $flag for a valid timestamp"); +            next; +        } +    } else { +        $opt_v && print STDERR "cannot open $flag\n"; +    } +    close(FLAG); +    ($state, $delta) = check_age($last_bak); +    $dir =~ /([^\/]+)\/?$/; +    $service = "backups-$1"; +    print_status($host, $state, "$delta hours old$extra_msg", $service); +    foreach my $vserver_dir (@vserver_dirs) { +        $vsdir = "$dir/$vserver_dir"; +        if (opendir(DIR, $vsdir)) { +            @vservers = grep { /^[^\.]/ && -d "$vsdir/$_" } readdir(DIR); +            $opt_v && print STDERR "found vservers $vsdir: @vservers\n"; +            closedir DIR; +        } else { +            $opt_v && print STDERR "no vserver in $vsdir\n"; +        } +    } +    my @dom_sufx = split(/\./, $host); +    my $dom_sufx = join('.', @dom_sufx[1,-1]); +    foreach my $vserver (@vservers) { +        print_status("$vserver.$dom_sufx", $state, "$delta hours old$extra_msg, same as parent: $host"); +    } +} + +sub check_age { +    my ($last_bak) = @_; +    my $t = time(); +    my $delta = $t - $last_bak; +    if ($delta > $opt_c) { +        $state = $STATE_CRITICAL; +    } elsif ($delta > $opt_w) { +        $state = $STATE_WARNING; +    } elsif ($delta >= 0) { +        $state = $STATE_OK; +    } +    $delta = sprintf '%.2f', $delta/3600.0; +    return ($state, $delta); +} + +sub print_status { +    my ($host, $state, $message, $service) = @_; +    my $state_msg = $ERRORS{$state}; +    if (!$service) { +        $service = 'backups'; +    } +    $line = "$host\t$service\t$state\t$state_msg $message\n"; +    if ($opt_s) { +	$opt_v && print STDERR "sending results to nagios...\n"; +        open(NSCA, "|/usr/sbin/send_nsca -H $opt_s") or die("cannot start send_nsca: $!\n"); +        print NSCA $line; +        close(NSCA) or warn("could not close send_nsca pipe correctly: $!\n"); +    } +    if (!$opt_s || $opt_v) { +        printf $line; +    } +} + +sub check_flag { +    my ($host, $flag) = @_; +    my @stats = stat($flag); +    if (not @stats) { +        print_status($host, $STATE_UNKNOWN, "cannot stat flag $flag"); +    } +    else { +        ($state, $delta) = check_age($stats[9]); +        print_status($host, $state, "$delta hours old"); +    } +} + +my $backupdir= $opt_d; + +my @hosts; +if (defined($opt_o)) { +	@hosts=qx{hostname -f}; +} else { +	# XXX: this should be a complete backup registry instead +	@hosts=qx{ls $backupdir | grep -v lost+found}; +} + +chdir($backupdir); +my ($delta, $state, $host); +foreach $host (@hosts) { +	chomp($host); +	if ($opt_o) { +		$dir = $backupdir; +	} else { +		$dir = $host; +	} +	my $flag; +	if (-d $dir) { +                # guess the backup type and find a proper stamp file to compare +                @rdiffs = glob("$dir/*/rdiff-backup-data"); +                foreach $subdir (@rdiffs) { +                    $subdir =~ s/rdiff-backup-data$//; +                    $opt_v && print STDERR "inspecting dir $subdir\n"; +                    check_rdiff($host, $subdir, $opt_v); +                    $flag = 1; +                } +		if (-d "$dir/dump") { +			# XXX: this doesn't check backup consistency +			$flag="$dir/dump/" . `ls -tr $dir/dump | tail -1`; +			chomp($flag); +			check_flag($host, $flag); +		} elsif (-d "$dir/dup") { +			# XXX: this doesn't check backup consistency +			$flag="$dir/dup/" . `ls -tr $dir/dup | tail -1`; +			chomp($flag); +			check_flag($host, $flag); +		} elsif (-r "$dir/rsync.log") { +			# XXX: this doesn't check backup consistency +			$flag="$dir/rsync.log"; +			check_flag($host, $flag); +		} +                if (!$flag) { +                        print_status($host, $STATE_UNKNOWN, 'unknown system'); +		} +	} else { +            print_status($host, $STATE_UNKNOWN, 'no directory'); +	} +} diff --git a/puppet/modules/backupninja/files/nagios_plugins/duplicity/README.md b/puppet/modules/backupninja/files/nagios_plugins/duplicity/README.md new file mode 100644 index 00000000..1cd349af --- /dev/null +++ b/puppet/modules/backupninja/files/nagios_plugins/duplicity/README.md @@ -0,0 +1,24 @@ +duplicity-backup-status +======================= + +Backupninja generates duplicity configfiles, this nagios plugin can check their freshness. Currently only the config files generated by backupninja can be parsed and we depend on that. + +## Prerequisites + +Make sure you have python-argparse installed (yes an extra dependency, getopt doubles the amount of code, so I gave up on that). The Python script will look for the duplicity_freshness.sh shell script in /usr/local/lib/nagios/plugins/ or /usr/lib/nagios/plugins/ make sure you copy it there and make executable.  + +## Getting started + +Run the python script from your nagios. Don't forget to specify some extras like when warnings or criticalities should be emerged. + +-  -w WARNINC   Number of hours allowed for incremential backup warning level default 28 +-  -W WARNFULL  Number of hours allowed for incremential backup critical level default 40 +-  -c CRITINC   Number of days allowed for full backup warning level default 52 +-  -C CRITFULL  Number of days allowed for full backup critical level default 60 + + +## TODO: + +- make it cuter, tidy up +- make it more robust +- support other config backends as backupninja - this can be done by writing more scripts like backupninja_duplicity_freshness.sh and parsing an extra parameter diff --git a/puppet/modules/backupninja/files/nagios_plugins/duplicity/backupninja_duplicity_freshness.sh b/puppet/modules/backupninja/files/nagios_plugins/duplicity/backupninja_duplicity_freshness.sh new file mode 100644 index 00000000..7af2bf7f --- /dev/null +++ b/puppet/modules/backupninja/files/nagios_plugins/duplicity/backupninja_duplicity_freshness.sh @@ -0,0 +1,268 @@ +#!/bin/bash +# -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*- +# vim: set filetype=sh sw=3 sts=3 expandtab autoindent: + +# Load backupninja library/helpers, because why reinventing the wheel? [Because my wheels weren't round] +# some duplication is to be expected +# this is only supposed to work with duplicity + +## Functions +# simple lowercase function +function tolower() { +   echo "$1" | tr '[:upper:]' '[:lower:]' +} + +# we grab the current time once, since processing +# all the configs might take more than an hour. +nowtime=`LC_ALL=C date +%H` +nowday=`LC_ALL=C date +%d` +nowdayofweek=`LC_ALL=C date +%A` +nowdayofweek=`tolower "$nowdayofweek"` + +conffile="/etc/backupninja.conf" + +# find $libdirectory +libdirectory=`grep '^libdirectory' $conffile | /usr/bin/awk '{print $3}'` +if [ -z "$libdirectory" ]; then +   if [ -d "/usr/lib/backupninja" ]; then +      libdirectory="/usr/lib/backupninja" +   else +      echo "Could not find entry 'libdirectory' in $conffile." +      fatal "Could not find entry 'libdirectory' in $conffile." +   fi +else +   if [ ! -d "$libdirectory" ]; then +      echo "Lib directory $libdirectory not found." +      fatal "Lib directory $libdirectory not found." +   fi +fi + +. $libdirectory/tools + +setfile $conffile + +# get global config options (second param is the default) +getconf configdirectory /etc/backup.d +getconf scriptdirectory /usr/share/backupninja +getconf reportdirectory +getconf reportemail +getconf reporthost +getconf reportspace +getconf reportsuccess yes +getconf reportinfo no +getconf reportuser +getconf reportwarning yes +getconf loglevel 3 +getconf when "Everyday at 01:00" +defaultwhen=$when +getconf logfile /var/log/backupninja.log +getconf usecolors "yes" +getconf SLAPCAT /usr/sbin/slapcat +getconf LDAPSEARCH /usr/bin/ldapsearch +getconf RDIFFBACKUP /usr/bin/rdiff-backup +getconf CSTREAM /usr/bin/cstream +getconf MYSQLADMIN /usr/bin/mysqladmin +getconf MYSQL /usr/bin/mysql +getconf MYSQLHOTCOPY /usr/bin/mysqlhotcopy +getconf MYSQLDUMP /usr/bin/mysqldump +getconf PGSQLDUMP /usr/bin/pg_dump +getconf PGSQLDUMPALL /usr/bin/pg_dumpall +getconf PGSQLUSER postgres +getconf GZIP /bin/gzip +getconf GZIP_OPTS --rsyncable +getconf RSYNC /usr/bin/rsync +getconf admingroup root + +if [ ! -d "$configdirectory" ]; then +   echo "Configuration directory '$configdirectory' not found." +   fatal "Configuration directory '$configdirectory' not found." +fi + +# get the duplicity configuration +function get_dupconf(){ +   setfile $1 +   getconf options +   getconf testconnect yes +   getconf nicelevel 0 +   getconf tmpdir +    +   setsection gpg +   getconf password +   getconf sign no +   getconf encryptkey +   getconf signkey +    +   setsection source +   getconf include +   getconf vsnames all +   getconf vsinclude +   getconf exclude +    +   setsection dest +   getconf incremental yes +   getconf increments 30 +   getconf keep 60 +   getconf keepincroffulls all +   getconf desturl +   getconf awsaccesskeyid +   getconf awssecretaccesskey +   getconf cfusername +   getconf cfapikey +   getconf cfauthurl +   getconf ftp_password +   getconf sshoptions +   getconf bandwidthlimit 0 +   getconf desthost +   getconf destdir +   getconf destuser +   destdir=${destdir%/} +} + +### some voodoo to mangle the correct commands + +function mangle_cli(){ + +   execstr_options="$options " +   execstr_source= +   if [ -n "$desturl" ]; then +      [ -z "$destuser" ] || warning 'the configured destuser is ignored since desturl is set' +      [ -z "$desthost" ] || warning 'the configured desthost is ignored since desturl is set' +      [ -z "$destdir" ] || warning 'the configured destdir is ignored since desturl is set' +      execstr_serverpart="$desturl" +   else +      execstr_serverpart="scp://$destuser@$desthost/$destdir" +   fi +    +    +   ### Symmetric or asymmetric (public/private key pair) encryption +   if [ -n "$encryptkey" ]; then +      execstr_options="${execstr_options} --encrypt-key $encryptkey" +   fi +    +   ### Data signing (or not) +   if [ "$sign" == yes ]; then +      # duplicity is not able to sign data when using symmetric encryption +      [ -n "$encryptkey" ] || fatal "The encryptkey option must be set when signing." +      # if needed, initialize signkey to a value that is not empty (checked above) +      [ -n "$signkey" ] || signkey="$encryptkey" +      execstr_options="${execstr_options} --sign-key $signkey" +   fi +    +   ### Temporary directory +   precmd= +   if [ -n "$tmpdir" ]; then +      if [ ! -d "$tmpdir" ]; then +         #info "Temporary directory ($tmpdir) does not exist, creating it." +         mkdir -p "$tmpdir" +         [ $? -eq 0 ] || fatal "Could not create temporary directory ($tmpdir)." +         chmod 0700 "$tmpdir" +      fi +      #info "Using $tmpdir as TMPDIR" +      precmd="${precmd}TMPDIR=$tmpdir " +   fi +    +   ### Source +    +   set -o noglob +    +   # excludes +   SAVEIFS=$IFS +   IFS=$(echo -en "\n\b") +   for i in $exclude; do +      str="${i//__star__/*}" +      execstr_source="${execstr_source} --exclude '$str'" +   done +   IFS=$SAVEIFS +    +   # includes +   SAVEIFS=$IFS +   IFS=$(echo -en "\n\b") +   for i in $include; do +      [ "$i" != "/" ] || fatal "Sorry, you cannot use 'include = /'" +      str="${i//__star__/*}" +      execstr_source="${execstr_source} --include '$str'" +   done +   IFS=$SAVEIFS +    +   set +o noglob +    +   execstr_options="${execstr_options} --ssh-options '$sshoptions'" +   if [ "$bandwidthlimit" != 0 ]; then +      [ -z "$desturl" ] || warning 'The bandwidthlimit option is not used when desturl is set.' +      execstr_precmd="trickle -s -d $bandwidthlimit -u $bandwidthlimit" +   fi +} + +#function findlastdates(){ +#   outputfile=$1 +#   lastfull=0 +#   lastinc=0 +#   backuptime=0 +#    +#   while read line; do +#      atime=0 +#      arr=() +#      sort='' +#      test=$(echo $line|awk '{if (NF == 7); if ($1 == "Full" || $1 == "Incremental") {print $4, $3, $6, $5}}'  ) +#    +#      if [ -n "$test"  ]; then +#         backuptime=$(date -u -d "$test" +%s) +#    +#         arr=($(echo $line|awk '{print $1, $2, $3, $4, $5, $6}')) +#         if [ ${arr[0]} == "Incremental" ] && [ "$lastinc" -lt "$backuptime" ] ; then +#            lastinc=$backuptime +#         elif [ ${arr[0]} == "Full" ] && [ "$lastfull" -lt "$backuptime" ] ; then +#            lastfull=$backuptime +#         fi +#    +#      fi +#    +#   done < $outputfile +#      # a full backup can be seen as incremental too +#      lastinc=$(echo $lastinc | awk 'max=="" || $1 > max {max=$1} END{ print max}') +#} + +function check_status() { +   grep -q 'No orphaned or incomplete backup sets found.' $1 +   if [ $? -ne 0 ] ; then +     exit 2 +   fi +} + +## +## this function handles the freshness check of a backup action +## + +function process_action() { +   local file="$1" +   local suffix="$2" +   setfile $file +   get_dupconf $1 +   mangle_cli +    +   outputfile=`maketemp backupout` +   export PASSPHRASE=$password +   export FTP_PASSWORD=$ftp_password +   output=` su -c \ +            "$execstr_precmd duplicity $execstr_options collection-status $execstr_serverpart >$outputfile 2>&1"` +   exit_code=$? +   echo -n $outputfile + +   #check_status +   #findlastdates +} + +files=`find $configdirectory -follow -mindepth 1 -maxdepth 1 -type f ! -name '.*.swp' | sort -n` + +for file in $files; do +   [ -f "$file" ] || continue +   suffix="${file##*.}" +   base=`basename $file` +   if [ "${base:0:1}" == "0" -o "$suffix" == "disabled" ]; then +      continue +   fi +   if [ -e "$scriptdirectory/$suffix" -a "$suffix" == "dup" ]; then +      process_action $file $suffix +   fi +done + diff --git a/puppet/modules/backupninja/files/nagios_plugins/duplicity/check_backupninja_duplicity.py b/puppet/modules/backupninja/files/nagios_plugins/duplicity/check_backupninja_duplicity.py new file mode 100644 index 00000000..8ed9ce68 --- /dev/null +++ b/puppet/modules/backupninja/files/nagios_plugins/duplicity/check_backupninja_duplicity.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python + +# Inspired by Arne Schwabe <arne-nagios@rfc2549.org> [with BSD license] +# Inspired by backupninja [that's gpl some version] +# minor changes by someon who doesn't understand all the license quirks + +from subprocess import Popen,PIPE +import sys +import time +import os +import argparse +import getopt + +def main(): +    # getopt = much more writing +    parser = argparse.ArgumentParser(description='Nagios Duplicity status checker') + +    parser.add_argument("-w", dest="warninc", default=28, type=int,  +                        help="Number of hours allowed for incremential backup warning level, default 28") +    parser.add_argument("-W", dest="warnfull", default=31, type=int,  +                        help="Number of days allowed for full backup warning level, default 31") +    parser.add_argument("-c", dest="critinc", default=52, type=int,  +                        help="Number of hours allowed for incremential backup critical level, default 52") +    parser.add_argument("-C", dest="critfull", default=33, type=int,  +                        help="Number of days allowed for full backup critical level, default 33") +    args = parser.parse_args() +     +    okay = 0 + +    # *sigh* check_output is from python 2.7 and onwards. Debian, upgrade yourself. +    #output , err = check_output(['/root/freshness.sh']) + +    if os.path.isfile("/usr/lib/nagios/plugins/backupninja_duplicity_freshness.sh") and os.access("/usr/lib/nagios/plugins/backupninja_duplicity_freshness.sh", os.X_OK): +      checkstatus, err = Popen(['/bin/bash', '/usr/lib/nagios/plugins/backupninja_duplicity_freshness.sh'], stdout=PIPE, stderr=PIPE, env={'HOME': '/root', 'PATH': os.environ['PATH']}).communicate() +    elif os.path.isfile("/usr/local/lib/nagios/plugins/backupninja_duplicity_freshness.sh") and os.access("/usr/local/lib/nagios/plugins/backupninja_duplicity_freshness.sh", os.X_OK): +      checkstatus, err = Popen(['/bin/bash', '/usr/local/lib/nagios/plugins/backupninja_duplicity_freshness.sh'], stdout=PIPE, stderr=PIPE, env={'HOME': '/root', 'PATH': os.environ['PATH']}).communicate() + +    # Don't use exec(), popen(), etc. to execute external commands without explicity using the full path of the external program.  Hijacked search path could be problematic. +    #checkstatus, err = Popen(['/bin/bash', './freshness.sh'], stdout=PIPE, stderr=PIPE, env={'HOME': '/root', 'PATH': os.environ['PATH']}).communicate() + +    #another sigh: Debian testing, upgrade yourself, this is only needed because Debian testing uses duplicity 0.6.18-3  +    # open file read/write +    f = open (checkstatus,"r") +    checklines = f.readlines() +    f.close() + +    # remove the line that says Import of duplicity.backends.giobackend Failed: No module named gio +    f = open(checkstatus,"w") +    for line in checklines: +      if not 'Import of duplicity.backends.giobackend Failed: No module named gio' in line: +        f.write(line) +    f.close() + +    output = open(checkstatus).read() + +    lastfull, lastinc = findlastdates(output) + +    sincelastfull = time.time() - lastfull  +    sincelastinc  =  time.time() - lastinc  + +    msg = "OK: " +     +    if sincelastfull > (args.warnfull * 24 * 3600) or sincelastinc > (args.warninc * 3600): +        okay = 1 +        msg = "WARNING: " +    if sincelastfull > (args.critfull * 24 * 3600) or sincelastinc > (args.critinc * 3600): +        okay = 2 +        msg = "CRITICAL: " +    if not checkoutput(output): +        okay = max(okay,1) +        msg = "WARNING: duplicity output: %s " % repr(output) +    if err: +        okay=2 +        msg = "Unexpected output: %s, " % repr(err) + +    print msg, "last full %s ago, last incremential %s ago|lastfull=%d, lastinc=%d" % ( formattime(sincelastfull), formattime(sincelastinc), sincelastfull, sincelastinc) +     +    #clean up cruft +    os.remove(checkstatus) +    sys.exit(okay) + +def checkoutput(output): +    if not 'No orphaned or incomplete backup sets found.' in output: +        return False +     +    return True + +def formattime(seconds): +    days = seconds / (3600 * 24) +    hours = seconds / 3600 % 24 + +    if days: +        return "%d days %d hours" % (days,hours) +    else: +        return "%d hours" % hours + + +def findlastdates(output): +    lastfull = 0 +    lastinc = 0 + +    for line in output.split("\n"): +        parts = line.split() + +        # ['Incremental', 'Sun', 'Oct', '31', '03:00:04', '2010', '1'] +        if len (parts) == 7 and parts[0] in ["Full","Incremental"]: +            foo = time.strptime(" ".join(parts[1:6]),"%a %b %d %H:%M:%S %Y") +     +            backuptime =  time.mktime(foo) +     +            if parts[0] == "Incremental" and lastinc < backuptime: +                lastinc = backuptime +            elif parts[0] == "Full" and lastfull < backuptime: +                lastfull = backuptime +         + +    # Count a full backup as incremental backup +    lastinc = max(lastfull,lastinc) +    return (lastfull, lastinc) +	 + +if __name__=='__main__': +   main() diff --git a/puppet/modules/backupninja/manifests/cron.pp b/puppet/modules/backupninja/manifests/cron.pp new file mode 100644 index 00000000..bd4e857c --- /dev/null +++ b/puppet/modules/backupninja/manifests/cron.pp @@ -0,0 +1,17 @@ +# Write the backupninja cron job, allowing you to specify an alternate backupninja +# command (if you want to wrap it in any other commands, e.g. to allow it to use +# the monkeysphere for authentication), or a different schedule to run it on. +define backupninja::cron( +  $backupninja_cmd = '/usr/sbin/backupninja', +  $backupninja_test_cmd = $backupninja_cmd, +  $cronfile = "/etc/cron.d/backupninja", +  $min = "0", $hour = "*", $dom = "*", $month = "*", +  $dow = "*") +{ +  file { $cronfile: +    content => template('backupninja/backupninja.cron.erb'), +    owner => root, +    group => root, +    mode => 0644 +  } +} diff --git a/puppet/modules/backupninja/manifests/duplicity.pp b/puppet/modules/backupninja/manifests/duplicity.pp new file mode 100644 index 00000000..a05da876 --- /dev/null +++ b/puppet/modules/backupninja/manifests/duplicity.pp @@ -0,0 +1,147 @@ +# Run duplicity-backup as part of a backupninja run. +# +# Valid attributes for this type are: +# +#   order: +# +#      The prefix to give to the handler config filename, to set order in +#      which the actions are executed during the backup run. +# +#   ensure: +# +#      Allows you to delete an entry if you don't want it any more (but be +#      sure to keep the configdir, name, and order the same, so that we can +#      find the correct file to remove). +# +#   options, nicelevel, testconnect, tmpdir, sign, encryptkey, signkey, +#   password, include, exclude, vsinclude, incremental, keep, bandwidthlimit, +#   sshoptions, destdir, desthost, desuser: +# +#      As defined in the backupninja documentation.  The options will be +#      placed in the correct sections automatically.  The include and +#      exclude options should be given as arrays if you want to specify +#      multiple directories. +# +#   directory, ssh_dir_manage, ssh_dir, authorized_keys_file, installuser, +#   installkey, backuptag: +# +#      Options for the bakupninja::server::sandbox define, check that +#      definition for more info. +# +# Some notes about this handler: +# +#   - When specifying a password, be sure to enclose it in single quotes, +#     this is particularly important if you have any special characters, such +#     as a $ which puppet will attempt to interpret resulting in a different +#     password placed in the file than you expect! +#   - There's no support for a 'local' type in backupninja's duplicity +#     handler on version 0.9.6-4, which is the version available in stable and +#     testing debian repositories by the time of this writing. +define backupninja::duplicity( $order  = 90, +                               $ensure = present, +                               # options to the config file +                               $options     = false, +                               $nicelevel   = false, +                               $testconnect = false, +                               $tmpdir      = false, +                               # [gpg] +                               $sign       = false, +                               $encryptkey = false, +                               $signkey    = false, +                               $password   = false, +                               # [source] +                               $include = [ "/var/spool/cron/crontabs", +                                            "/var/backups", +                                            "/etc", +                                            "/root", +                                            "/home", +                                            "/usr/local/*bin", +                                            "/var/lib/dpkg/status*" ], +                               $exclude = [ "/home/*/.gnupg", +                                            "/home/*/.local/share/Trash", +                                            "/home/*/.Trash", +                                            "/home/*/.thumbnails", +                                            "/home/*/.beagle", +                                            "/home/*/.aMule", +                                            "/home/*/.gnupg", +                                            "/home/*/.gpg", +                                            "/home/*/.ssh", +                                            "/home/*/gtk-gnutella-downloads", +                                            "/etc/ssh/*" ], +                               $vsinclude = false, +                               # [dest] +                               $incremental   = "yes", +                               $increments   = false, +                               $keep          = false, +                               $keepincroffulls = false, +                               $bandwidthlimit = false, +                               $sshoptions    = false, +                               $destdir       = false, +                               $desthost      = false, +                               $destuser      = false, +                               $desturl       = false, +                               # configs to backupninja client +                               $backupkeystore       = $backupninja::keystore, +                               $backupkeystorefspath = $backupninja::keystorefspath, +                               $backupkeytype        = $backupninja::keytype, +                               $backupkeydest        = $backupninja::keydest, +                               $backupkeydestname    = $backupninja::keydestname, +                               # options to backupninja server sandbox +                               $ssh_dir_manage       = true, +                               $ssh_dir              = "${destdir}/.ssh", +                               $authorized_keys_file = 'authorized_keys', +                               $installuser          = true, +                               $backuptag            = "backupninja-${::fqdn}", +                               # key options +                               $createkey            = false, +                               $keymanage            = $backupninja::keymanage ) { + +  # install client dependencies +  ensure_resource('package', 'duplicity', {'ensure' => $backupninja::ensure_duplicity_version}) + +  case $desthost { false: { err("need to define a destination host for remote backups!") } } +  case $destdir { false: { err("need to define a destination directory for remote backups!") } } +  case $password { false: { err("a password is necessary either to unlock the GPG key, or for symmetric encryption!") } } + +  # guarantees there's a configured backup space for this backup +  backupninja::server::sandbox { "${user}-${name}": +    user                 => $destuser, +    host                 => $desthost, +    dir                  => $destdir, +    manage_ssh_dir       => $ssh_dir_manage, +    ssh_dir              => $ssh_dir, +    authorized_keys_file => $authorized_keys_file, +    installuser          => $installuser, +    backuptag            => $backuptag, +    backupkeys           => $backupkeystore, +    keytype              => $backupkeytype, +  } + +  # the client's ssh key +  backupninja::key { "${destuser}-${name}": +    user           => $destuser, +    createkey      => $createkey, +    keymanage      => $keymanage, +    keytype        => $backupkeytype, +    keystore       => $backupkeystore, +    keystorefspath => $backupkeystorefspath, +    keydest        => $backupkeydest, +    keydestname    => $backupkeydestname +  } + +  # the backupninja rule for this duplicity backup +  file { "${backupninja::configdir}/${order}_${name}.dup": +    ensure  => $ensure, +    content => template('backupninja/dup.conf.erb'), +    owner   => root, +    group   => root, +    mode    => 0600, +    require => File["${backupninja::configdir}"] +  } + +  if $backupninja::manage_nagios { +    nagios::service::passive { $nagios_description: } +  } + +} + diff --git a/puppet/modules/backupninja/manifests/generate_sshkey.pp b/puppet/modules/backupninja/manifests/generate_sshkey.pp new file mode 100644 index 00000000..a3008e50 --- /dev/null +++ b/puppet/modules/backupninja/manifests/generate_sshkey.pp @@ -0,0 +1,33 @@ +define backupninja::generate_sshkey( +  $ssh_key_basepath = '/etc/puppet/modules/keys/files/backupkeys', +){ + +  # generate backupninja ssh keypair +  $ssh_key_name = "backup_${::hostname}_id_rsa" +  $ssh_keys = ssh_keygen("${ssh_key_basepath}/${ssh_key_name}") +  $public = split($ssh_keys[1],' ') +  $public_type = $public[0] +  $public_key = $public[1] + +  file { '/root/.ssh': +    ensure => directory, +    owner  => 'root', +    group  => 'root', +    mode   => '0600'; +  } + +  # install ssh keypair on client +  file { "/root/.ssh/$ssh_key_name": +    content => $ssh_keys[0], +    owner   => root, +    group   => 0, +    mode    => '0600'; +  } + +  file { "/root/.ssh/$ssh_key_name.pub": +    content => $public_key, +    owner   => root, +    group   => 0, +    mode    => '0666'; +  } +} diff --git a/puppet/modules/backupninja/manifests/init.pp b/puppet/modules/backupninja/manifests/init.pp new file mode 100644 index 00000000..e453e703 --- /dev/null +++ b/puppet/modules/backupninja/manifests/init.pp @@ -0,0 +1,52 @@ +# configure backupninja +class backupninja ( +  $ensure_backupninja_version = 'installed', +  $ensure_rsync_version = 'installed', +  $ensure_rdiffbackup_version = 'installed', +  $ensure_debconfutils_version = 'installed', +  $ensure_hwinfo_version = 'installed', +  $ensure_duplicity_version = 'installed', +  $configdir = '/etc/backup.d', +  $keystore = "${::fileserver}/keys/backupkeys", +  $keystorefspath = false, +  $keytype = 'rsa', +  $keydest = '/root/.ssh', +  $keyowner = 0, +  $keygroup = 0, +  $keymanage = true, +  $configfile = '/etc/backupninja.conf', +  $loglvl = 4, +  $when = 'everyday at 01:00', +  $reportemail = 'root', +  $reportsuccess = false, +  $reportwarning = true, +  $reporthost = undef, +  $reportuser = undef, +  $reportdirectory = undef, +  $logfile = '/var/log/backupninja.log', +  $scriptdir = '/usr/share/backupninja', +  $libdir = '/usr/lib/backupninja', +  $usecolors = true, +  $vservers = false, +  $manage_nagios = false, +) { + +  # install client dependencies +  ensure_resource('package', 'backupninja', {'ensure' => $ensure_backupninja_version}) + +  # set up backupninja config directory +  file { $configdir: +    ensure => directory, +    mode   => '0750', +    owner  => 0, +    group  => 0; +  } + +  file { $configfile: +    content => template('backupninja/backupninja.conf.erb'), +    owner   => root, +    group   => 0, +    mode    => '0644' +  } + +} diff --git a/puppet/modules/backupninja/manifests/key.pp b/puppet/modules/backupninja/manifests/key.pp new file mode 100644 index 00000000..9d34cdbd --- /dev/null +++ b/puppet/modules/backupninja/manifests/key.pp @@ -0,0 +1,41 @@ +# generate and deploy backupninja sshkeys +define backupninja::key( +  $user = $name, +  $createkey = false, +  $keymanage = $backupninja::keymanage, +  $keyowner = $backupninja::keyowner, +  $keygroup = $backupninja::keygroup, +  $keystore= $backupninja::keystore, +  $keystorefspath = $backupninja::keystorefspath, +  $keytype = $backupninja::keytype, +  $keydest = $backupninja::keydest, +  $keydestname = "id_${backupninja::keytype}" ) +{ + +  # generate the key +  if $createkey == true { +    if $keystorefspath == false { +      err('need to define a destination directory for sshkey creation!') +    } +    $ssh_keys = ssh_keygen("${keystorefspath}/${keydestname}") +  } + +  # deploy/manage the key +  if $keymanage == true { +    $keydestfile = "${keydest}/${keydestname}" +    ensure_resource('file', $keydest, { +      'ensure' => 'directory', +      'mode'   => '0700', +      'owner'  => $keyowner, +      'group'  => $keygroup +    }) +    ensure_resource('file', $keydestfile, { +      'ensure'  => 'present', +      'source'  => "${keystore}/${user}_id_${keytype}", +      'mode'    => '0700', +      'owner'   => $keyowner, +      'group'   => $keygroup, +      'require' => File[$keydest], +    }) +  } +} diff --git a/puppet/modules/backupninja/manifests/labelmount.pp b/puppet/modules/backupninja/manifests/labelmount.pp new file mode 100644 index 00000000..8974cec1 --- /dev/null +++ b/puppet/modules/backupninja/manifests/labelmount.pp @@ -0,0 +1,62 @@ +# Mount a labelled partition on a directory as part of a backupninja run. +# +# This type will automatically create an unmount action with an order of 99 +# for the destination directory you specify here. +# +# Valid attributes for this type are: +# +#   order: The prefix to give to the handler config filename, to set +#      order in which the actions are executed during the backup run.  Note +#      that the value given here should be less than any action which +#      requires the filesystem to be mounted! +# +#   ensure: Allows you to delete an entry if you don't want it any more +#      (but be sure to keep the configdir, name, and order the same, so +#      that we can find the correct file to remove). +# +#   label: The partition label to mount. +# +#   dest: The directory to mount the partition onto. +#  +define backupninja::labelmount($order = 10, +                               $ensure = present, +                               $label, +                               $dest +                              ) { +	file { "${backupninja::configdir}/${order}_${name}.labelmount": +		ensure => $ensure, +		content => template('backupninja/labelmount.conf.erb'), +		owner => root, +		group => root, +		mode => 0600, +		require => File["${backupninja::configdir}"] +	} + +	file { "${backupninja::configdir}/99_${name}.umount": +		ensure => $ensure, +		content => template('backupninja/umount.conf.erb'), +		owner => root, +		group => root, +		mode => 0600, +		require => File["${backupninja::configdir}"] +	} +	 +	# Copy over the handler scripts themselves, since they're not in the +	# standard distribution, and are unlikely to end up there any time +	# soon because backupninja's "build" system is balls. +	file { "/usr/share/backupninja/labelmount": +		content => template('backupninja/labelmount.handler'), +		owner => root, +		group => root, +		mode => 0755, +		require => Package[backupninja] +	} + +	file { "/usr/share/backupninja/umount": +		content => template('backupninja/umount.handler'), +		owner => root, +		group => root, +		mode => 0755, +		require => Package[backupninja] +	} +} diff --git a/puppet/modules/backupninja/manifests/maildir.pp b/puppet/modules/backupninja/manifests/maildir.pp new file mode 100644 index 00000000..2454b82d --- /dev/null +++ b/puppet/modules/backupninja/manifests/maildir.pp @@ -0,0 +1,43 @@ +# maildir handler, as part of a backupninja run. +# +# The maildir handler slowly creates a backup of each user's +# maildir to a remote server. It is designed to be run with +# low overhead in terms of CPU and bandwidth, so it runs pretty +# slow. Hardlinking is used to save storage space. The actual +# maildir is stored within each snapshot directory. +# +# Valid attributes for this type are: +# +#   order: The prefix to give to the handler config filename, to set +#      order in which the actions are executed during the backup run. +# +#   ensure: Allows you to delete an entry if you don't want it any more +#      (but be sure to keep the configdir, name, and order the same, so +#      that we can find the correct file to remove). +# +#  +define backupninja::maildir( +  $order = 99, $ensure = present, +  $when = 'everyday at 21:00', $srcdir = false, +  $destdir = false, $desthost = false, $destuser = false, $destid_file = false, +  $remove = false, $multiconnection = yes, $keepdaily='4', $keepweekly='2', +  $keepmonthly='2') +{ +  # install client dependencies +  ensure_resource('package', 'rsync', {'ensure' => $backupninja::ensure_rsync_version}) + +  case $srcdir { false: { err("need to define a source directory to backup!") } } +  case $destdir { false: { err("need to define a destination directory to backup!") } } +  case $desthost { false: { err("need to define a destination host for backups!") } } +  case $destuser { false: { err("need to define a destination user for backups!") } } +  case $destid_file { false: { err("need to define a ssh key id file to use!") } } +   +  file { "${backupninja::configdir}/${order}_${name}.maildir": +    ensure => $ensure, +    content => template('backupninja/maildir.conf.erb'), +    owner => root, +    group => root, +    mode => 0600, +    require => File["${backupninja::configdir}"] +  } +} diff --git a/puppet/modules/backupninja/manifests/mysql.pp b/puppet/modules/backupninja/manifests/mysql.pp new file mode 100644 index 00000000..b8877c05 --- /dev/null +++ b/puppet/modules/backupninja/manifests/mysql.pp @@ -0,0 +1,38 @@ +# Safe MySQL dumps, as part of a backupninja run. +# +# Valid attributes for this type are: +# +#   order: The prefix to give to the handler config filename, to set +#      order in which the actions are executed during the backup run. +# +#   ensure: Allows you to delete an entry if you don't want it any more +#      (but be sure to keep the configdir, name, and order the same, so +#      that we can find the correct file to remove). +# +#   user, dbusername, dbpassword, dbhost, databases, backupdir, +#   hotcopy, sqldump, compress, configfile: As defined in the +#   backupninja documentation, with the caveat that hotcopy, sqldump, +#   and compress take true/false rather than yes/no. +#  +define backupninja::mysql( +  $order = 10, $ensure = present, $user = false, $dbusername = false, $dbpassword = false, +  $dbhost = 'localhost', $databases = 'all', $backupdir = false, $hotcopy = false, +  $sqldump = false, $compress = false, $configfile = true, +  $vsname = false, $sqldumpoptions = '--lock-tables --complete-insert --add-drop-table --quick --quote-names', +  $nodata = false) +{ +   +  $real_configfile = $configfile ? { +    true => "/etc/mysql/debian.cnf", +    default => $configfile, +  } + +  file { "${backupninja::configdir}/${order}_${name}.mysql": +    ensure => $ensure, +    content => template('backupninja/mysql.conf.erb'), +    owner => root, +    group => root, +    mode => 0600, +    require => File["${backupninja::configdir}"] +  } +} diff --git a/puppet/modules/backupninja/manifests/nagios_plugin/duplicity.pp b/puppet/modules/backupninja/manifests/nagios_plugin/duplicity.pp new file mode 100644 index 00000000..7dbd2633 --- /dev/null +++ b/puppet/modules/backupninja/manifests/nagios_plugin/duplicity.pp @@ -0,0 +1,45 @@ +class backupninja::nagios_plugin::duplicity { +  case $::operatingsystem { +    'Debian': { package { 'python-argparse': ensure => installed, } } +    'Ubuntu': { package { 'python-argh':     ensure => installed, } } +    default:  { +      notify {'Backupninja-Duplicity Nagios check needs python-argparse to be installed !':}  } +  } + +  file { '/usr/lib/nagios/plugins/check_backupninja_duplicity.py': +    source => 'puppet:///modules/backupninja/nagios_plugins/duplicity/check_backupninja_duplicity.py', +    mode   => '0755', +    owner  => 'nagios', +    group  => 'nagios', +  } + +  # deploy helper script +  file { '/usr/lib/nagios/plugins/backupninja_duplicity_freshness.sh': +    source => 'puppet:///modules/backupninja/nagios_plugins/duplicity/backupninja_duplicity_freshness.sh', +    mode   => '0755', +    owner  => 'nagios', +    group  => 'nagios', +  } + +  nagios::nrpe::command { 'check_backupninja_duplicity': +    command_line => "sudo ${::nagios::nrpe::nagios_plugin_dir}/check_backupninja_duplicity.py" +  } +  sudo::spec {'nrpe_check_backupninja_duplicity': +      ensure    => present, +      users     => 'nagios', +      hosts     => 'ALL', +      commands  => "NOPASSWD: ${::nagios::nrpe::nagios_plugin_dir}/check_backupninja_duplicity.py"; +  } + +  nagios::service { "Backupninja Duplicity $::fqdn": +    use_nrpe              => true, +    check_command         => 'check_backupninja_duplicity', +    nrpe_timeout          => '60', +    # check only twice a day +    normal_check_interval => '720', +    # recheck every hour +    retry_check_interval  => '60', +  } + + +} diff --git a/puppet/modules/backupninja/manifests/pgsql.pp b/puppet/modules/backupninja/manifests/pgsql.pp new file mode 100644 index 00000000..d4814be9 --- /dev/null +++ b/puppet/modules/backupninja/manifests/pgsql.pp @@ -0,0 +1,27 @@ +# Safe PGSQL dumps, as part of a backupninja run. +# +# Valid attributes for this type are: +# +#   order: The prefix to give to the handler config filename, to set +#      order in which the actions are executed during the backup run. +# +#   ensure: Allows you to delete an entry if you don't want it any more +#      (but be sure to keep the configdir, name, and order the same, so +#      that we can find the correct file to remove). +# +#   backupdir, compress, configfile: As defined in the +#   backupninja documentation, with the caveat that hotcopy, sqldump, +#   and compress take true/false rather than yes/no. +#  +define backupninja::pgsql( +  $order = 10, $ensure = present, $databases = 'all', $backupdir = "/var/backups/postgres", $compress = true, $vsname = false) +{ +  file { "${backupninja::configdir}/${order}_${name}.pgsql": +    ensure => $ensure, +    content => template('backupninja/pgsql.conf.erb'), +    owner => root, +    group => root, +    mode => 0600, +    require => File["${backupninja::configdir}"] +  } +} diff --git a/puppet/modules/backupninja/manifests/rdiff.pp b/puppet/modules/backupninja/manifests/rdiff.pp new file mode 100644 index 00000000..cd73d22c --- /dev/null +++ b/puppet/modules/backupninja/manifests/rdiff.pp @@ -0,0 +1,109 @@ +# Run rdiff-backup as part of a backupninja run. +# +# Valid attributes for this type are: +# +#   order: The prefix to give to the handler config filename, to set +#      order in which the actions are executed during the backup run. +# +#   ensure: Allows you to delete an entry if you don't want it any more +#      (but be sure to keep the configdir, name, and order the same, so +#      that we can find the correct file to remove). +# +#   keep, include, exclude, type, host, directory, user, sshoptions: As +#      defined in the backupninja documentation.  The options will be placed +#      in the correct sections automatically.  The include and exclude +#      options should be given as arrays if you want to specify multiple +#      directories. +#  +define backupninja::rdiff( $order  = 90, +                           $ensure = present, +                           # [general] +                           $options = '--force', +                           $extras  = false, +                           # [source] +                           $include = [ "/var/spool/cron/crontabs", +                                        "/var/backups", +                                        "/etc", +                                        "/root", +                                        "/home", +                                        "/usr/local/*bin", +                                        "/var/lib/dpkg/status*" +                                      ], +                           $exclude = [ "/home/*/.gnupg", +                                        "/home/*/.local/share/Trash", +                                        "/home/*/.Trash", +                                        "/home/*/.thumbnails", +                                        "/home/*/.beagle", +                                        "/home/*/.aMule", +                                        "/home/*/gtk-gnutella-downloads" +                                      ], +                           $vsinclude = false, +                           # [dest] +                           $type       = 'local', +                           $host       = false, +                           $user       = false, +                           $home       = "/home/${user}-${name}", +                           $keep       = 30, +                           $sshoptions = false, +                           # ssh keypair config +                           $key            = false, +                           $keymanage      = $backupninja::keymanage, +                           $backupkeystore = $backupninja::keystore, +                           $backupkeytype  = $backupninja::keytype, +                           $ssh_dir_manage = true, +                           $ssh_dir        = "${home}/.ssh", +                           $authorized_keys_file = 'authorized_keys', +                           # sandbox config +                           $installuser = true, +                           $backuptag   = "backupninja-${::fqdn}", +                           # monitoring +                           $nagios_description = "backups-${name}" ) { + +  # install client dependencies +  ensure_resource('package', 'rdiff-backup', {'ensure' => $backupninja::ensure_rdiffbackup_version}) + +  $directory = "$home/$name/" + +  case $type { +    'remote': { +      case $host { false: { err("need to define a host for remote backups!") } } + +      backupninja::server::sandbox { "${user}-${name}": +        user                 => $user, +        host                 => $host, +        dir                  => $home, +        manage_ssh_dir       => $ssh_dir_manage, +        ssh_dir              => $ssh_dir, +        key                  => $key, +        authorized_keys_file => $authorized_keys_file, +        installuser          => $installuser, +        backuptag            => $backuptag, +        backupkeys           => $backupkeystore, +        keytype              => $backupkeytype, +      } +      +      backupninja::key { "${user}-${name}": +        user      => $user, +        keymanage => $keymanage, +        keytype   => $backupkeytype, +        keystore  => $backupkeystore, +      } +    } +  } + + +  file { "${backupninja::configdir}/${order}_${name}.rdiff": +    ensure  => $ensure, +    content => template('backupninja/rdiff.conf.erb'), +    owner   => root, +    group   => root, +    mode    => 0600, +    require => File["${backupninja::configdir}"] +  } + +  if $backupninja::manage_nagios { +    nagios::service::passive { $nagios_description: } +  } + +} +   diff --git a/puppet/modules/backupninja/manifests/rsync.pp b/puppet/modules/backupninja/manifests/rsync.pp new file mode 100644 index 00000000..fc59950b --- /dev/null +++ b/puppet/modules/backupninja/manifests/rsync.pp @@ -0,0 +1,128 @@ +# Run rsync as part of a backupninja run. +# Based on backupninja::rdiff + +define backupninja::rsync( $order  = 90, +                           $ensure = present, +                           # [general] +                           $log             = false, +                           $partition       = false, +                           $fscheck         = false, +                           $read_only       = false, +                           $mountpoint      = false, +                           $format          = false, +                           $days            = false, +                           $keepdaily       = false, +                           $keepweekly      = false, +                           $keepmonthly     = false, +                           $lockfile        = false, +                           $nicelevel       = 0, +                           $tmp             = false, +                           $multiconnection = false, +                           $enable_mv_timestamp_bug = false, +                           # [source] +                           $include = [ "/var/spool/cron/crontabs", +                                        "/var/backups", +                                        "/etc", +                                        "/root", +                                        "/home", +                                        "/usr/local/*bin", +                                        "/var/lib/dpkg/status*" +                                      ], +                           $exclude = [ "/home/*/.gnupg", +                                        "/home/*/.local/share/Trash", +                                        "/home/*/.Trash", +                                        "/home/*/.thumbnails", +                                        "/home/*/.beagle", +                                        "/home/*/.aMule", +                                        "/home/*/gtk-gnutella-downloads" +                                      ], +                           # [dest] +                           $host           = false, +                           $user           = false, +                           $home           = "/home/${user}-${name}", +                           $subfolder      = 'rsync', +                           $testconnect    = false, +                           $ssh            = false, +                           $protocol       = false, +                           $numericids     = false, +                           $compress       = false, +                           $port           = false, +                           $bandwidthlimit = false, +                           $remote_rsync   = false, +                           $batch          = false, +                           $batchbase      = false, +                           $fakesuper      = false, +                           $id_file        = false, +                           # [services] +                           $initscripts = false, +                           $service     = false, +                           # [system] +                           $rm    = false, +                           $cp    = false, +                           $touch = false, +                           $mv    = false, +                           $fsck  = false, +                           # ssh keypair config +                           $key                  = false, +                           $keymanage            = $backupninja::keymanage, +                           $backupkeystore       = $backupninja::keystore, +                           $backupkeytype        = $backupninja::keytype, +                           $ssh_dir_manage       = true, +                           $ssh_dir              = "${home}/.ssh", +                           $authorized_keys_file = 'authorized_keys', +                           # sandbox config +                           $installuser = true, +                           $backuptag   = "backupninja-${::fqdn}", +                           # monitoring +                           $nagios_description = "backups-${name}" ) { + +  # install client dependencies +  ensure_resource('package', 'rsync', {'ensure' => $backupninja::ensure_rsync_version}) + +  # Right now just local origin with remote destination is supported. +  $from = 'local' +  $dest = 'remote' + +  case $dest { +    'remote': { +      case $host { false: { err("need to define a host for remote backups!") } } + +      $directory = "${home}/${subfolder}/" + +      backupninja::server::sandbox { "${user}-${name}": +        user                 => $user, +        host                 => $host, +        dir                  => $home, +        manage_ssh_dir       => $ssh_dir_manage, +        ssh_dir              => $ssh_dir, +        key                  => $key, +        authorized_keys_file => $authorized_keys_file, +        installuser          => $installuser, +        backuptag            => $backuptag, +        keytype              => $backupkeytype, +        backupkeys           => $backupkeystore, +      } +      +      backupninja::key { "${user}-${name}": +        user       => $user, +        keymanage  => $keymanage, +        keytype    => $backupkeytype, +        keystore   => $backupkeystore, +      } +    } +  } + +  file { "${backupninja::configdir}/${order}_${name}.rsync": +    ensure  => $ensure, +    content => template('backupninja/rsync.conf.erb'), +    owner   => root, +    group   => root, +    mode    => 0600, +    require => File["${backupninja::configdir}"] +  } + +  if $backupninja::manage_nagios { +    nagios::service::passive { $nagios_description: } +  } + +} diff --git a/puppet/modules/backupninja/manifests/server.pp b/puppet/modules/backupninja/manifests/server.pp new file mode 100644 index 00000000..49e42a0f --- /dev/null +++ b/puppet/modules/backupninja/manifests/server.pp @@ -0,0 +1,147 @@ +# this define realizes all needed resources for a hosted backup +define backupninja_server_realize($host) { +  User               <<| tag == "backupninja-$host" |>> +  File               <<| tag == "backupninja-$host" |>> +  Ssh_authorized_key <<| tag == "backupninja-$host" |>> +} + +class backupninja::server ( +  $backupdir = '/backup', +  $backupdir_ensure = 'directory', +  $manage_nagios = false, +  $nagios_server = undef, +  $nagios_warn_level = 129600, +  $nagios_crit_level = 216000, +) { + +  group { "backupninjas": +    ensure => "present", +    gid => 700 +  } +   +  file { $backupdir: +    ensure => $backupdir_ensure, +    mode => 0710, owner => root, group => "backupninjas", +    require => $backupdir_ensure ? { +      'directory' => undef, +      default     => File["$backupdir_ensure"], +    } +  } + +  if $manage_nagios { + +    case $nagios_server { undef: { err('Cannot manage nagios without nagios_server parameter!') } } + +    include nagios::nsca::client +     +    file { "/usr/local/bin/checkbackups": +      ensure => "present", +      source => "puppet:///modules/backupninja/checkbackups.pl", +      mode => 0755, owner => root, group => root, +    } + +    cron { checkbackups: +      command => "/usr/local/bin/checkbackups -d ${backupdir} -s ${nagios_server} -w ${nagios_warn_level} -c ${nagios_crit_level} | grep -v 'sent to host successfully'", +      user => "root", +      hour => "8-23", +      minute => 59, +      require => [ File["/usr/local/bin/checkbackups"], Package['nsca'] ] +    } +  } + +  # collect all resources from hosted backups +  Backupninja_server_realize <<| tag == $::fqdn |>> + +  # this define allows nodes to declare a remote backup sandbox, that have to +  # get created on the server +  define sandbox ( +    $user = $name, +    $host = $::fqdn, +    $installuser = true, +    $dir, +    $manage_ssh_dir = true, +    $ssh_dir = "${dir}/.ssh", +    $authorized_keys_file = 'authorized_keys', +    $key = false, +    $keytype = 'dss', +    $backupkeys = "${fileserver}/keys/backupkeys", +    $uid = false, +    $gid = "backupninjas", +    $backuptag = "backupninja-${::fqdn}", +  ) { + +    if !defined(Backupninja_server_realize["${::fqdn}@${host}"]) { +      @@backupninja_server_realize { "${::fqdn}@${host}": +        host => $::fqdn, +        tag  => $host, +      } +    } + +    if !defined(File["$dir"]) { +      @@file { "$dir": +        ensure => directory, +        mode => 0750, owner => $user, group => 0, +        tag => "$backuptag", +      } +    } + +    if $installuser { + +       if $manage_ssh_dir { +        if !defined(File["$ssh_dir"]) { +          @@file { "${ssh_dir}": +            ensure => directory, +            mode => 0700, owner => $user, group => 0, +            require => [User[$user], File["$dir"]], +            tag => "$backuptag", +          } +         } +       }  + +      if $key { +        # $key contais ssh public key +        if !defined(Ssh_autorized_key["$user"]) { +          @@ssh_authorized_key{ "$user": +            type    => $keytype, +            key     => $key, +            user    => $user, +            target  => "${ssh_dir}/${authorized_keys_file}", +            tag     => "$backuptag", +            require => User[$user], +          } +        } +      } +      else { +        # get ssh public key exists from server +        if !defined(File["${ssh_dir}/${authorized_keys_file}"]) { +          @@file { "${ssh_dir}/${authorized_keys_file}": +            ensure => present, +            mode => 0644, owner => 0, group => 0, +            source => "${backupkeys}/${user}_id_${keytype}.pub", +            require => File["${ssh_dir}"], +            tag => "$backuptag", +          } +        } +      } +       +      if !defined(User["$user"]) { +        @@user { "$user": +          ensure   => "present", +          uid      => $uid ? { +              false   => undef, +              default => $uid +          }, +          gid      => "$gid", +          comment  => "$user backup sandbox", +          home     => "$dir", +          managehome => true, +          shell    => "/bin/bash", +          password => '*', +          require  => Group['backupninjas'], +          tag      => "$backuptag" +        } +      } +    } +  } +} + diff --git a/puppet/modules/backupninja/manifests/sh.pp b/puppet/modules/backupninja/manifests/sh.pp new file mode 100644 index 00000000..4a60e5fa --- /dev/null +++ b/puppet/modules/backupninja/manifests/sh.pp @@ -0,0 +1,25 @@ +# sh handler, as part of a backupninja run. +# +# Valid attributes for this type are: +# +#   order: The prefix to give to the handler config filename, to set +#      order in which the actions are executed during the backup run. +# +#   ensure: Allows you to delete an entry if you don't want it any more +#      (but be sure to keep the configdir, name, and order the same, so +#      that we can find the correct file to remove). +# +#  +define backupninja::sh($order = 50, +                           $ensure = present, +                           $command_string +                          ) { +	file { "${backupninja::configdir}/${order}_${name}.sh": +		ensure => $ensure, +		content => template('backupninja/sh.conf.erb'), +		owner => root, +		group => root, +		mode => 0600, +		require => File["${backupninja::configdir}"] +	} +} diff --git a/puppet/modules/backupninja/manifests/svn.pp b/puppet/modules/backupninja/manifests/svn.pp new file mode 100644 index 00000000..1ab0597f --- /dev/null +++ b/puppet/modules/backupninja/manifests/svn.pp @@ -0,0 +1,28 @@ +# Subversion dumps, as part of a backupninja run. +# +# Valid attributes for this type are: +# +#   order: The prefix to give to the handler config filename, to set +#      order in which the actions are executed during the backup run. +# +#   ensure: Allows you to delete an entry if you don't want it any more +#      (but be sure to keep the configdir, name, and order the same, so +#      that we can find the correct file to remove). +# +#  +define backupninja::svn($order = 20, +                           $ensure = present, +                           $src = '/var/lib/svn', +                           $dest = '/var/backups/svn', +                           $tmp = '/var/backups/svn.tmp', +                           $vsname = false +                          ) { +	file { "${backupninja::configdir}/${order}_${name}.svn": +		ensure => $ensure, +		content => template('backupninja/svn.conf.erb'), +		owner => root, +		group => root, +		mode => 0600, +		require => File["${backupninja::configdir}"] +	} +} diff --git a/puppet/modules/backupninja/manifests/sys.pp b/puppet/modules/backupninja/manifests/sys.pp new file mode 100644 index 00000000..946a525e --- /dev/null +++ b/puppet/modules/backupninja/manifests/sys.pp @@ -0,0 +1,45 @@ +# sys handler, as part of a backupninja run. +# +# Valid attributes for this type are: +# +#   order: The prefix to give to the handler config filename, to set +#      order in which the actions are executed during the backup run. +# +#   ensure: Allows you to delete an entry if you don't want it any more +#      (but be sure to keep the configdir, name, and order the same, so +#      that we can find the correct file to remove). +# +#  +define backupninja::sys($order = 30, +                           $ensure = present, +                           $parentdir = '/var/backups', +                           $packages = true, +                           $packagesfile = '/var/backups/dpkg-selections.txt', +                           $partitions = true, +                           $partitionsfile = '/var/backups/partitions.__star__.txt', +                           $dosfdisk = true, +                           $hardware = true, +                           $hardwarefile = '/var/backups/hardware.txt', +                           $dohwinfo = true, +                           $doluks = false, +                           $dolvm = false +                          ) { + +  # install client dependencies +  case $operatingsystem { +    debian,ubuntu: { +      ensure_resource('package', 'debconf-utils', {'ensure' => $backupninja::ensure_debconfutils_version}) +      ensure_resource('package', 'hwinfo', {'ensure' => $backupninja::ensure_hwinfo_version}) +    } +    default: {} +  } + +	file { "${backupninja::configdir}/${order}_${name}.sys": +		ensure => $ensure, +		content => template('backupninja/sys.conf.erb'), +		owner => root, +		group => root, +		mode => 0600, +		require => File["${backupninja::configdir}"] +	} +} diff --git a/puppet/modules/backupninja/templates/backupninja.conf.erb b/puppet/modules/backupninja/templates/backupninja.conf.erb new file mode 100644 index 00000000..7706a615 --- /dev/null +++ b/puppet/modules/backupninja/templates/backupninja.conf.erb @@ -0,0 +1,25 @@ +# This configuration file was auto-generated by the Puppet configuration +# management system.  Any changes you make to this file will be overwritten +# the next time Puppet runs.  Please make configuration changes to this +# service in Puppet. + +loglevel = <%= @loglvl %> +when = <%= send(:when) %> +reportemail = <%= @reportemail %> +reportsuccess = <%= @reportsuccess ? 'yes' : 'no' %> +reportwarning = <%= @reportwarning ? 'yes' : 'no' %> +<% if reporthost.is_a? String -%> +<%= 'reporthost = ' + @reporthost %> +<% end -%> +<% if reportuser.is_a? String -%> +<%= 'reportuser = ' + @reportuser %> +<% end -%> +<% if reportdirectory.is_a? String -%> +<%= 'reportdirectory = ' + @reportdirectory %> +<% end -%> +logfile = <%= @logfile %> +configdirectory = <%= @configdir %> +scriptdirectory = <%= @scriptdir %> +libdirectory = <%= @libdir %> +usecolors = <%= @usecolors ? 'yes' : 'no' %> +vservers = <%= @vservers ? 'yes' : 'no' %> diff --git a/puppet/modules/backupninja/templates/backupninja.cron.erb b/puppet/modules/backupninja/templates/backupninja.cron.erb new file mode 100644 index 00000000..ec392ca9 --- /dev/null +++ b/puppet/modules/backupninja/templates/backupninja.cron.erb @@ -0,0 +1,6 @@ +# /etc/cron.d/backupninja -- cron tab entry for package backupninja + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +# # run backupninja  +<%= min %> <%= hour %> <%= dom %> <%= month %> <%= dow %> root if [ -x <%= backupninja_test_cmd %> ]; then <%= backupninja_cmd %>; fi diff --git a/puppet/modules/backupninja/templates/dup.conf.erb b/puppet/modules/backupninja/templates/dup.conf.erb new file mode 100644 index 00000000..4f15e789 --- /dev/null +++ b/puppet/modules/backupninja/templates/dup.conf.erb @@ -0,0 +1,46 @@ +# This configuration file was auto-generated by the Puppet configuration +# management system.  Any changes you make to this file will be overwritten +# the next time Puppet runs.  Please make configuration changes to this +# service in Puppet. + +<%= 'options = ' + options if options %> +<%= 'nicelevel = ' + nicelevel if nicelevel %> +<%= 'testconnect = ' + testconnect if testconnect %> +<%= 'tmpdir = ' + tmpdir if tmpdir %> + +[gpg] +<%= 'sign = ' + sign if sign %> +<%= 'encryptkey = ' + encryptkey if encryptkey %> +<%= 'signkey = ' + signkey if signkey %> +<%= 'password = ' + password if password %> + +[source] +<% if include.is_a? String -%> +<%= 'include = ' + include %> +<% elsif include.is_a? Array -%> +<%= include.map { |i| "include = #{i}" }.join("\n") %> +<% end -%> + +<% if exclude.is_a? String -%> +<%= 'exclude = ' + exclude %> +<% elsif exclude.is_a? Array -%> +<%= exclude.map { |i| "exclude = #{i}" }.join("\n") %> +<% end -%> + +<% if vsinclude.is_a? String -%> +<%= 'vsinclude = ' + vsinclude %> +<% elsif vsinclude.is_a? Array -%> +<%= vsinclude.map { |i| "vsinclude = #{i}" }.join("\n") %> +<% end -%> + +[dest] +<%= 'incremental = ' + incremental if incremental %> +<%= 'increments = ' + increments if increments %> +<%= 'keep = ' + keep if keep %> +<%= 'keepincroffulls = ' + keepincroffulls if keepincroffulls %> +<%= 'bandwidthlimit = ' + bandwidthlimit if bandwidthlimit %> +<%= 'sshoptions = ' + sshoptions if sshoptions %> +<%= 'destdir = ' + destdir if destdir %> +<%= 'desthost = ' + desthost if desthost %> +<%= 'destuser = ' + destuser if destuser %> +<%= 'desturl = ' + desturl if desturl %> diff --git a/puppet/modules/backupninja/templates/labelmount.conf.erb b/puppet/modules/backupninja/templates/labelmount.conf.erb new file mode 100644 index 00000000..e40c49d3 --- /dev/null +++ b/puppet/modules/backupninja/templates/labelmount.conf.erb @@ -0,0 +1,2 @@ +label = <%= label %> +dest = <%= dest %> diff --git a/puppet/modules/backupninja/templates/labelmount.handler b/puppet/modules/backupninja/templates/labelmount.handler new file mode 100644 index 00000000..22090bd4 --- /dev/null +++ b/puppet/modules/backupninja/templates/labelmount.handler @@ -0,0 +1,17 @@ +#!/bin/sh + +# Mount a block device with the specified label ('label') onto the given +# directory ('dest'). + +getconf label +getconf dest + +if [ ! -b "/dev/disk/by-label/$label" ]; then +	halt "No partition labelled '$label' is available" +fi + +if [ ! -d "$dest" ]; then +	halt "Destination directory does not exist" +fi + +mount -t auto /dev/disk/by-label/$label $dest || halt "Mount failed" diff --git a/puppet/modules/backupninja/templates/maildir.conf.erb b/puppet/modules/backupninja/templates/maildir.conf.erb new file mode 100644 index 00000000..351f3824 --- /dev/null +++ b/puppet/modules/backupninja/templates/maildir.conf.erb @@ -0,0 +1,14 @@ +# This configuration file was auto-generated by the Puppet configuration +# management system.  Any changes you make to this file will be overwritten +# the next time Puppet runs.  Please make configuration changes to this +# service in Puppet. + +<% %w{when srcdir destdir desthost destuser destid_file keepdaily keepweekly keepmonthly}.each do |v| +	if send(v) +		-%><%= v + ' = ' + send(v) + "\n" %><% +	end +end -%> + +remove = <%= remove ? 'yes' : 'no' %> +multiconnection = <%= multiconnection ? 'yes' : 'no' %> + diff --git a/puppet/modules/backupninja/templates/mysql.conf.erb b/puppet/modules/backupninja/templates/mysql.conf.erb new file mode 100644 index 00000000..b7ac5e8f --- /dev/null +++ b/puppet/modules/backupninja/templates/mysql.conf.erb @@ -0,0 +1,25 @@ +# This configuration file was auto-generated by the Puppet configuration +# management system.  Any changes you make to this file will be overwritten +# the next time Puppet runs.  Please make configuration changes to this +# service in Puppet. + +<% %w{user dbusername dbpassword dbhost databases backupdir vsname sqldumpoptions}.each do |v| +	if send(v) +		-%><%= v + ' = ' + send(v) + "\n" %><% +	end +end -%> + +hotcopy = <%= hotcopy ? 'yes' : 'no' %> +sqldump = <%= sqldump ? 'yes' : 'no' %> +compress = <%= compress ? 'yes' : 'no' %> + +<% if real_configfile %> +configfile = <%= real_configfile %> +<% end %> + +<% if nodata.is_a? String -%> +<%= 'nodata = ' + nodata %> +<% elsif nodata.is_a? Array -%> +<%= "nodata = " + nodata.map { |i| "#{i}" }.join(" ") %> +<% end -%> + diff --git a/puppet/modules/backupninja/templates/pgsql.conf.erb b/puppet/modules/backupninja/templates/pgsql.conf.erb new file mode 100644 index 00000000..5ffa89c0 --- /dev/null +++ b/puppet/modules/backupninja/templates/pgsql.conf.erb @@ -0,0 +1,13 @@ +<% if vsname %> +vsname = <%= vsname %> +<% end %> +<% if backupdir %> +backupdir = <%= backupdir %> +<% end %> +<% if databases.is_a? String -%> +<%= 'databases = ' + databases %> +<% elsif databases.is_a? Array -%> +<%= "databases = " + databases.map { |i| "#{i}" }.join(" ") %> +<% end -%> +compress = <%= compress ? 'yes' : 'no' %> + diff --git a/puppet/modules/backupninja/templates/rdiff.conf.erb b/puppet/modules/backupninja/templates/rdiff.conf.erb new file mode 100644 index 00000000..23c336fc --- /dev/null +++ b/puppet/modules/backupninja/templates/rdiff.conf.erb @@ -0,0 +1,38 @@ +# This configuration file was auto-generated by the Puppet configuration +# management system.  Any changes you make to this file will be overwritten +# the next time Puppet runs.  Please make configuration changes to this +# service in Puppet. + +<%= 'options = ' + options if options %> + +<%= extras if extras %> + +[source] +type = local +<%= 'keep = ' + keep if keep %> + +<% if include.is_a? String -%> +<%= 'include = ' + include %> +<% elsif include.is_a? Array -%> +<%= include.map { |i| "include = #{i}" }.join("\n") %> +<% end -%> + +<% if exclude.is_a? String -%> +<%= 'exclude = ' + exclude %> +<% elsif exclude.is_a? Array -%> +<%= exclude.map { |i| "exclude = #{i}" }.join("\n") %> +<% end -%> + +<% if vsinclude.is_a? String -%> +<%= 'vsinclude = ' + vsinclude %> +<% elsif vsinclude.is_a? Array -%> +<%= vsinclude.map { |i| "vsinclude = #{i}" }.join("\n") %> +<% end -%> + +[dest] +<%- %w{type host directory user sshoptions}.each do |v| +    if has_variable?(v) and instance_variable_get("@#{v}").to_s != "false" -%> +<%= v + ' = ' + instance_variable_get("@#{v}").to_s %> +<%- +    end +end -%> diff --git a/puppet/modules/backupninja/templates/rsync.conf.erb b/puppet/modules/backupninja/templates/rsync.conf.erb new file mode 100644 index 00000000..778676fc --- /dev/null +++ b/puppet/modules/backupninja/templates/rsync.conf.erb @@ -0,0 +1,49 @@ +# This configuration file was auto-generated by the Puppet configuration +# management system.  Any changes you make to this file will be overwritten +# the next time Puppet runs.  Please make configuration changes to this +# service in Puppet. + +[general] +<%- %w{log partition fscheck read_only mountpoint backupdir format days keepdaily keepweekly keepmonthly lockfile nicelevel enable_mv_timestamp_bug, tmp, multiconnection}.each do |v| +    if has_variable?(v) and instance_variable_get("@#{v}").to_s != "false" -%> +<%= v + ' = ' + instance_variable_get("@#{v}").to_s %> +<%- +    end +end -%> + +[source] +<% unless from.empty? and from.to_s != "false" -%> +from = <%= from %> +<% end -%> +<%- %w{include exclude}.each do |v| +    if has_variable?(v) +      instance_variable_get("@#{v}").to_a.each do |parameter| -%> +<%= v + ' = ' + parameter %> +<%- +      end +    end +end -%> + +[dest] +<%- %w{dest testconnect ssh protocol numericids compress host port user id_file bandwidthlimit remote_rsync batch batchbase fakesuper}.each do |v| +    if has_variable?(v) and instance_variable_get("@#{v}").to_s != "false" -%> +<%= v + ' = ' + instance_variable_get("@#{v}").to_s %> +<%- +    end +end -%> + +[services] +<%- %w{initscripts service}.each do |v| +    if has_variable?(v) and instance_variable_get("@#{v}").to_s != "false" -%> +<%= v + ' = ' + instance_variable_get("@#{v}").to_s %> +<%- +    end +end -%> + +[system] +<%- %w{rm cp touch mv fsck}.each do |v| +    if has_variable?(v) and instance_variable_get("@#{v}").to_s != "false" -%> +<%= v + ' = ' + instance_variable_get("@#{v}").to_s %> +<%- +    end +end -%> diff --git a/puppet/modules/backupninja/templates/sh.conf.erb b/puppet/modules/backupninja/templates/sh.conf.erb new file mode 100644 index 00000000..f1b4161a --- /dev/null +++ b/puppet/modules/backupninja/templates/sh.conf.erb @@ -0,0 +1,10 @@ +#!/bin/sh +# +# This configuration file was auto-generated by the Puppet configuration +# management system.  Any changes you make to this file will be overwritten +# the next time Puppet runs.  Please make configuration changes to this +# service in Puppet. + +<% @command_string.each_line do |line| -%> +<%= line %> +<% end -%> diff --git a/puppet/modules/backupninja/templates/svn.conf.erb b/puppet/modules/backupninja/templates/svn.conf.erb new file mode 100644 index 00000000..465cc673 --- /dev/null +++ b/puppet/modules/backupninja/templates/svn.conf.erb @@ -0,0 +1,10 @@ +# This configuration file was auto-generated by the Puppet configuration +# management system.  Any changes you make to this file will be overwritten +# the next time Puppet runs.  Please make configuration changes to this +# service in Puppet. + +<% %w{src dest tmp vsname}.each do |v| +	if send(v) +		-%><%= v + ' = ' + send(v) + "\n" %><% +	end +end -%>
\ No newline at end of file diff --git a/puppet/modules/backupninja/templates/sys.conf.erb b/puppet/modules/backupninja/templates/sys.conf.erb new file mode 100644 index 00000000..a684e8b7 --- /dev/null +++ b/puppet/modules/backupninja/templates/sys.conf.erb @@ -0,0 +1,18 @@ +# This configuration file was auto-generated by the Puppet configuration +# management system.  Any changes you make to this file will be overwritten +# the next time Puppet runs.  Please make configuration changes to this +# service in Puppet. + +<% %w{parentdir packagesfile partitionsfile hardwarefile}.each do |v| +	if send(v) +		-%><%= v + ' = ' + send(v) + "\n" %><% +	end +end -%> + +packages = <%= packages ? 'yes' : 'no' %> +partitions = <%= partitions ? 'yes' : 'no' %> +dosfdisk = <%= dosfdisk ? 'yes' : 'no' %> +hardware = <%= hardware ? 'yes' : 'no' %> +dohwinfo = <%= dohwinfo ? 'yes' : 'no' %> +luksheaders = <%= doluks ? 'yes' : 'no' %> +lvm = <%= dolvm ? 'yes' : 'no' %> diff --git a/puppet/modules/backupninja/templates/umount.conf.erb b/puppet/modules/backupninja/templates/umount.conf.erb new file mode 100644 index 00000000..59bfaec8 --- /dev/null +++ b/puppet/modules/backupninja/templates/umount.conf.erb @@ -0,0 +1 @@ +dir = <%= dest %> diff --git a/puppet/modules/backupninja/templates/umount.handler b/puppet/modules/backupninja/templates/umount.handler new file mode 100644 index 00000000..4fea195a --- /dev/null +++ b/puppet/modules/backupninja/templates/umount.handler @@ -0,0 +1,15 @@ +#!/bin/sh + +# Unmount the specified directory ('dir'), forcefully if necessary. + +getconf dir + +if ! umount $dir; then +	warning "Simple unmount failed for $dir; being forceful" +	if ! umount -f $dir; then +		warning "Forceful unmount failed for $dir; being lazy" +		if ! umount -l $dir; then +			warning "Lazy unmount failed for $dir; you're on your own" +		fi +	fi +fi | 
