Version information
This version is compatible with:
Start using this module
Add this module to your Puppetfile:
mod 'rharrison-bacula', '0.6.1'
Learn more about managing modules with a PuppetfileDocumentation
bacula
Author: Carl Caum carl@puppetlabs.com Copyright (c) 2011, Puppet Labs Inc.
Author: Russell Harrison rharrison@fedoraproject.org Copyright (c) 2012-2013, Russell Harrison
About
This module manages the Bacula backup solution. Through
declaration of the bacula
class, you can configure Directors, Storage Daemons,
Clients, and consoles.
This module is a fork of the Puppet Labs Bacula module.
Requirements
- Puppet >=2.6
- Puppetlabs/stdlib module. Can be obtained
here or with the command
puppet-module install puppetlabs/stdlib
MySQL Database Backend
- Puppetlabs/mysql module. Can be obtained
here or with the command
puppet-module install puppetlabs/mysql
- Declare the
mysql::server
class to set up a MySQL server on the Bacula director node and setmanage_db
to true to have the bacula module manage the MySQL database.
SQLite Database backend
- Puppetlabs/sqlite module. Can be obtained
here or with the command
puppet-module install puppetlabs/sqlite
Installation
The module can be obtained from the github repository.
- Select
Downloads
and thenDownload as tar.gz
which downloads a tar.gz archive. - Upload the tar.gz file to your Puppet Master.
- Untar the file. This will create a new directory called
rharrison10-rharrison-bacula-${commit_hash}
.- Rename this directory to just
bacula
and place it in your modulepath.
Configuration
There is one class (bacula
) that needs to be declared on all nodes managing
any component of Bacula. These nodes are configured using the parameters of
this class.
Using Parameterized Classes
Declaration example:
class { 'bacula':
console_password => 'consolepassword',
director_password => 'directorpassword',
director_server => 'bacula.example.com',
is_client => true,
is_director => true,
is_storage => true,
mail_to => 'bacula-admin@example.com',
manage_console => true,
storage_server => 'bacula.example.com',
}
Parameters
The following lists all the class parameters the bacula
class accepts.
clients
For directors, clients
is a hash of clients. The keys are the clients while
the values are a hash of parameters. The parameters accepted are the same as
the bacula::client::config
define.
console_password
The password to use for the console resource on the director
console_template
The ERB template to use for configuring the bconsole
instead of the one
included with the module
db_backend
Which database back end system you want to use to store the catalog data
director_password
The director's password
director_server
The FQDN of the Bacula director
director_template
The ERB template to use for configuring the director instead of the one included with the module
is_client
Whether the node should be a client
is_director
Whether the node should be a director
is_storage
Whether the node should be a storage server
logwatch_enabled
If manage_logwatch
is true
should the Bacula logwatch configuration be
enabled or disabled
mail_command
The command bacula will use to send mail.
Defaults to "/usr/sbin/bsmtp -h localhost -f bacula@${::fqdn} -s \"Bacula %t %e (for %c)\" %r"
.
mail_to
Send the message to this email address for all jobs. Will default to
root@${::fqdn}
if it and mail_to_on_error
are left undefined.
mail_to_daemon
Send daemon messages to this email address. Will default to either $mail_to
or $mail_to_on_error
in that order if left undefined.
mail_to_on_error
Send the message to this email address if the Job terminates with an error condition.
mail_to_operator
Send the message to this email addresse for mount messages. Will default to
either $mail_to
or $mail_to_on_error
in that order if left undefined.
manage_bat
Whether the bat should be managed on the node
manage_config_dir
Whether to purge all non-managed files from the bacula config directory
manage_console
Whether the bconsole
should be managed on the node
manage_db
Whether to manage creation of the database specified by db_database
. Defaults
to false. In order for this to work, you must declare the mysql::server
class
manage_db_tables
Whether to manage the SQL tables in the database specified by db_backend
.
Defaults to true
.
manage_logwatch
Whether to configure logwatch on the director
operator_command
The command bacula will use to send mail for Operator messages.
Defaults to "/usr/sbin/bsmtp -h localhost -f bacula@${::fqdn} -s \"Bacula Intervention Required (for %c)\" %r"
.
plugin_dir
The directory Bacula plugins are stored in. Use this parameter if you are
providing Bacula plugins for use. Only use if the package in the distro
repositories supports plugins or you have included a respository with a newer
Bacula packaged for your distro. If this is anything other than undef
and you
are not providing any plugins in this directory Bacula will throw an error
every time it starts even if the package supports plugins.
storage_default_mount
Directory where the default disk for file backups is mounted. A subdirectory
named default
will be created allowing you to define additional devices in
Bacula which use the same disk. Defaults to '/mnt/bacula'
.
storage_server
The FQDN of the storage server
storage_template
The ERB template to use for configuring the storage daemon instead of the one included with the module
tls_allowed_cn
Array of common name attribute of allowed peer certificates. If this directive is specified, all server certificates will be verified against this list. This can be used to ensure that only the CA-approved Director may connect.
tls_ca_cert
The full path and filename specifying a PEM encoded TLS CA certificate(s).
Multiple certificates are permitted in the file. One of
TLS CA Certificate File
or TLS CA Certificate Dir
are required in a server
context if TLS Verify Peer
is also specified, and are always required in a
client context.
tls_ca_cert_dir
Full path to TLS CA certificate directory. In the current implementation,
certificates must be stored PEM encoded with OpenSSL-compatible hashes, which
is the subject name's hash and an extension of .0. One of
TLS CA Certificate File
or TLS CA Certificate Dir
are required in a server
context if TLS Verify Peer
is also specified, and are always required in a
client context.
tls_cert
The full path and filename of a PEM encoded TLS certificate. It can be used as either a client or server certificate. PEM stands for Privacy Enhanced Mail, but in this context refers to how the certificates are encoded. It is used because PEM files are base64 encoded and hence ASCII text based rather than binary. They may also contain encrypted information.
tls_key
The full path and filename of a PEM encoded TLS private key. It must correspond to the TLS certificate.
tls_require
Require TLS connections. This directive is ignored unless TLS Enable
is set
to yes
. If TLS is not required, and TLS is enabled, then Bacula will connect
with other daemons either with or without TLS depending on what the other
daemon requests. If TLS is enabled and TLS is required, then Bacula will refuse
any connection that does not use TLS. Valid values are 'yes'
or 'no'
.
tls_verify_peer
Verify peer certificate. Instructs server to request and verify the client's
x509 certificate. Any client certificate signed by a known-CA will be accepted
unless the TLS Allowed CN
configuration directive is used, in which case the
client certificate must correspond to the Allowed Common Name specified.
Valid values are 'yes'
or 'no'
.
use_console
Whether to configure a console resource on the director
use_tls
Whether to use Bacula TLS - Communications Encryption.
use_vol_purge_script
Run a script to automatically clean up old volumes from the default file pool
after the BackupCatalog job is run each day. It is only valid if the Director
and the Storage daemon are running on the same host. true
or false
(default).
use_vol_purge_mvdir
The volume purge script can move volume files to a side directory for further
inspection instead of removing the volume files. Bacula has a tendency (at
least as of version 5.0.x) to occasionally label volume files incorrectly or
store jobs in a volume labeled differently than the job name. Takes an absolute
file file path to a directory or undef
the default.
volume_autoprune
Auto prune volumes in the default pool.
volume_autoprune_diff
Auto prune volumes in the default differential pool.
volume_autoprune_full
Auto prune volumes in the default full pool.
volume_autoprune_incr
Auto prune volumes in the default incremental pool.
volume_retention
Length of time to retain volumes in the default pool.
volume_retention_diff
Length of time to retain volumes in the default differential pool.
volume_retention_full
Length of time to retain volumes in the default full pool.
volume_retention_incr
Length of time to retain volumes in the default incremental pool.
Custom FileSets
bacula::director::fileset
Parameters
ensure
Ensure the file is present or absent. The only valid values are file
or
absent
. Defaults to file
.
exclude_files
An array of strings consisting of one file or directory name per entry. Directory names should be specified without a trailing slash with Unix path notation.
include_files
Required: An array of strings consisting of one file or directory name per entry. Directory names should be specified without a trailing slash with Unix path notation.
Custom Director configuration
For the highly likely case (given Bacula's complexity) where more complex configuration is needed you can include a file of additional configurations from your own modules.
bacula::director::custom_config
Parameters
ensure
Ensure the file is present or absent. The only valid values are file
or
absent
. Defaults to file
.
content
String containing the content for the configuration file. Usually supplied with a template.
source
The source location of the configuration file to deploy in bacula-dir.d
.
Clients
To back up clients on your network, you need to tell the director about them.
The director is whichever node you included the bacula
class and you specified
the parameter is_director
to true
. The way to add clients is different
depending on if you're using
exported resources,
or a hash of client information provided to the bacula
class's clients
parameter on the director node. Each will need to know the parameters of the
bacula::client::config
defined resource.
bacula::client::config
Parameters
ensure
If the configuration should be deployed to the director. file
(default),
present
, or absent
.
backup_enable
If the backup job for the client should be enabled 'yes'
(default)
or 'no'
.
client_schedule
The schedule for backups to be performed.
db_backend
The database back end of the catalog storing information about the backup
director_password
The director's password the client is connecting to.
director_server
The FQDN of the director server the client will connect to.
fileset
The file set used by the client for backups
pool
The pool used by the client for backups
pool_diff
The pool to use for differential backups. Setting this to false
will prevent
configuring a specific pool for differential backups. Defaults to
"${pool}.differential"
.
pool_full
The pool to use for full backups. Setting this to false
will prevent
configuring a specific pool for full backups. Defaults to "${pool}.full"
.
pool_incr
The pool to use for incremental backups. Setting this to false
will prevent
configuring a specific pool for incremental backups. Defaults to
"${pool}.incremental"
.
priority
This directive permits you to control the order in which your jobs will be run
by specifying a positive non-zero number. The higher the number, the lower the
job priority. Assuming you are not running concurrent jobs, all queued jobs of
priority 1
will run before queued jobs of priority 2
and so on, regardless
of the original scheduling order. The priority only affects waiting jobs that
are queued to run, not jobs that are already running. If one or more jobs of
priority 2
are already running, and a new job is scheduled with priority 1
,
the currently running priority 2
jobs must complete before the priority 1 job
is run, unless Allow Mixed Priority
is set. The default priority is 10
.
rerun_failed_levels
If this directive is set to 'yes'
(default 'no'
), and Bacula detects that a
previous job at a higher level (i.e. Full or Differential) has failed, the
current job level will be upgraded to the higher level. This is particularly
useful for Laptops where they may often be unreachable, and if a prior Full
save has failed, you wish the very next backup to be a Full save rather than
whatever level it is started as.
There are several points that must be taken into account when using this
directive: first, a failed job is defined as one that has not terminated
normally, which includes any running job of the same name (you need to ensure
that two jobs of the same name do not run simultaneously); secondly, the
Ignore FileSet Changes
directive is not considered when checking for failed
levels, which means that any FileSet change will trigger a rerun.
restore_enable
If the restore job for the client should be enabled 'yes'
(default)
or 'no'
.
restore_where
The default path to restore files to defined in the restore job for this client.
run_scripts
An array of hashes containing the parameters for any RunScripts
to include in the backup job definition. For each hash in the array a
RunScript
directive block will be inserted with the key = value
settings
from the hash. Note: The RunsWhen
key is required.
storage_server
The storage server hosting the pool this client will backup to
tls_ca_cert
The full path and filename specifying a PEM encoded TLS CA certificate(s).
Multiple certificates are permitted in the file. One of
TLS CA Certificate File
or TLS CA Certificate Dir
are required in a server
context if TLS Verify Peer
is also specified, and are always required in a
client context.
tls_ca_cert_dir
Full path to TLS CA certificate directory. In the current implementation,
certificates must be stored PEM encoded with OpenSSL-compatible hashes, which
is the subject name's hash and an extension of .0. One of
TLS CA Certificate File
or TLS CA Certificate Dir
are required in a server
context if TLS Verify Peer
is also specified, and are always required in a
client context.
tls_require
Require TLS connections. This directive is ignored unless TLS Enable
is set
to yes
. If TLS is not required, and TLS is enabled, then Bacula will connect
with other daemons either with or without TLS depending on what the other
daemon requests. If TLS is enabled and TLS is required, then Bacula will refuse
any connection that does not use TLS. Valid values are 'yes'
or 'no'
.
use_tls
Whether to use Bacula TLS - Communications Encryption.
Using Exported Resources
Exported resources are probably the most flexible way of deploying this module involving the least amount of admin interaction to be successful. The drawback is the intense overhead of stored configurations on your Puppet master.
Example
node /web-server\d+/ {
$director_password = 'directorpassword'
$director_server = "bacula-dir1.${::domain}"
# First install and configure bacula-fd pointing to the director.
class { 'bacula':
director_password => $director_password,
director_server => $director_server,
is_client => true,
storage_server => $director_server,
}
# Now we declare the exported resource so that it will be available to
# install the needed configuration on the director server
@@bacula::client::config { $::fqdn:
client_schedule => 'WeeklyCycle',
director_password => $director_password,
director_server => $director_server,
fileset => 'Basic:noHome',
storage_server => $director_server,
}
}
node /bacula-dir\d+/ {
$director_password = 'directorpassword'
$director_server = $::fqdn
# Lets set up the director server.
class { '::bacula':
console_password => 'consolepassword',
director_password => $director_password,
director_server => $director_server,
is_client => false,
is_director => true,
is_storage => true,
mail_to => "admin@${::domain}",
storage_server => $director_server,
}
# Now lets realize all of the exported client config resources configured to
# backup to this director server.
Bacula::Client::Config <<| director_server == $::fqdn |>>
}
Using clients
Parameter Hash
The bacula
class takes a clients
parameter. The value for clients
must
be a hash with the keys of the hash being the FQDN of the client. The value of
the client needs to be a hash containing the parameters for each client.
The advantage of this approach is that it can be implemented without stored
configurations which will allow for scaling your Puppet masters much further.
The disadvantage is that the clients
hash must be maintained by hand or by
an external provider such as an ENC, heira, or some other means which
introduces maintanance overhead and / or complexity in your environment.
Example
node /web-server\d+/ {
$director_password = 'directorpassword'
$director_server = "bacula-dir1.${::domain}"
# First install and configure bacula-fd pointing to the director.
class { 'bacula':
director_password => $director_password,
director_server => $director_server,
is_client => true,
storage_server => $director_server,
}
}
node /bacula-dir\d+/ {
$director_password = 'directorpassword'
$director_server = $::fqdn
# Now we setup the clients hash so the configuration files can be created
# for the director config.
# Note the values for the director and storage parameters will be derived
# from the values passed to the `bacula::director` class so they only have to
# be provided if they are different.
$bacula_clients = {
"web-server1.${::domain}" => {
client_schedule => 'WeeklyCycle',
fileset => 'Basic:noHome',
},
"web-server2.${::domain}" => {
client_schedule => 'WeeklyCycle',
fileset => 'Basic:noHome',
},
}
# Lets set up the director server.
class { '::bacula':
clients => $bacula_clients,
console_password => 'consolepassword',
director_password => $director_password,
director_server => $director_server,
is_client => false,
is_director => true,
is_storage => true,
mail_to => "admin@${::domain}",
storage_server => $director_server,
}
# Now lets realize all of the exported client config resources configured to
# backup to this director server.
Bacula::Client::Config <<| director_server == $::fqdn |>>
}
Included FileSets
Basic:noHome
Include
/boot
/etc
/usr/local
/var
/opt
/srv
Exclude
/var/cache
/var/tmp
/var/lib/apt
/var/lib/dpkg
/var/lib/puppet
/var/lib/mysql
/var/lib/postgresql
/var/lib/ldap
/var/lib/bacula
/var/lib/yum
Basic:withHome
Include
/home
/boot
/etc
/usr/local
/var
/opt
/srv
Exclude
/var/cache
/var/tmp
/var/lib/apt
/var/lib/dpkg
/var/lib/puppet
/var/lib/mysql
/var/lib/postgresql
/var/lib/ldap
/var/lib/bacula
/var/lib/yum
Included Schedules
WeeklyCycle
- Full First Sun at 23:05
- Differential Second-Fifth Sun at 23:05
- Incremental Mon-Sat at 23:05
WeeklyCycleAfterBackup
- Full Mon-Sun at 23:10
Weekly:onFriday
- Full First Fri at 18:30
- Differential Second-Fifth Fri at 18:30
- Incremental Sat-Thu at 20:00
Weekly:onSaturday
- Full First Sat at 15:30
- Differential Second-Fifth Sat at 15:30
- Incremental Sun-Fri at 20:00
Weekly:onSunday
- Full First Sun at 15:30
- Differential Second-Fifth Sun at 15:30
- Incremental Mon-Sat at 20:00
Weekly:onMonday
- Full First Mon at 18:30
- Differential Second-Fifth Mon at 18:30
- Incremental Tue-Sun at 20:00
Weekly:onTuesday
- Full First Tue at 18:30
- Differential Second-Fifth Tue at 18:30
- Incremental Wed-Mon at 20:00
Weekly:onWednesday
- Full First Wed at 18:30
- Differential Second-Fifth Wed at 18:30
- Incremental Thu-Tue at 20:00
Weekly:onThursday
- Full First Thu at 18:30
- Differential Second-Fifth Thu at 18:30
- Incremental Fri-Wed at 20:00
Hourly
- Incremental hourly at 0:30
Templates
The Bacula module comes with templates that set default Fileset resources. To
configure different Filesets, copy the bacula-dir.conf.erb
file out of the
bacula/templates
directory to another location in your manifests (can be
another module). Make the modifications you want and set the
director_template
parameter (listed above) to point to the path where you have
stored the custom template.
TODO
- Add ability to create custom Filesets.
- Add ability to create custom schedules.
- Add ability to configure storage servers external to the director.
- Add ability to configure multiple pools on a storage server
- PostgreSQL support
- rspec-puppet unit tests.
2015-09-07 Russell Harrison rharrison@fedoraproject.org - 0.6.1
- Minor changes to resolve automated code quality checks on the forge.
2015-09-14 Russell Harrison rharrison@fedoraproject.org - 0.6.0
- Add script to automattically remove volume files that are no longer needed.
2015-01-07 Russell Harrison rharrison@fedoraproject.org - 0.5.1
- Fix priority for client jobs.
2014-12-12 Russell Harrison rharrison@fedoraproject.org - 0.5.0
- Add the option to set the priority for a backup job.
- Fix deprecated variable access in the templates
2013-10-17 Russell Harrison rharrison@fedoraproject.org - 0.4.1
- Work around a bug in v1.0.0 of the puppetlabs-mysql module that causes the mysql_grant type to notify on every run by having the mysql_database resource created in the mysql::db define notify Exec['make_db_tables'] directly.
2013-06-28 Russell Harrison rharrison@fedoraproject.org - 0.4.0
- Add an option to disable client backup and / or restore jobs
- Add an option to ensure client configs are present or absent
2013-06-11 Russell Harrison rharrison@fedoraproject.org - 0.3.1
- Reload bacula-dir configuration if files are removed from bacula-dir.d
2013-05-30 Russell Harrison rharrison@fedoraproject.org - 0.3.0
- Fix bug where the volume retention period for the default pool was getting passed to the default incremental pool
- Instead of restarting the bacula-dir service which could interrupt running jobs tell the director to reload its configuration
- Added ability to decide if volumes in the default pools are auto pruned or not.
2013-05-14 Russell Harrison rharrison@fedoraproject.org - 0.2.0
- Move to absolute qualification of variables and classes to avoid https://projects.puppetlabs.com/issues/17335
- Add options for setting the email adress for the Mail, Mail On Error, and Operator destinations for standard messages and the Mail destination for daemon messages.
- Removeing purge command from database backup job since it isn't working correctly
- Only configure plugin dir if plugins are provided
2013-04-08 Russell Harrison rharrison@fedoraproject.org - 0.1.0
- Add abbility to configure 'Rerun Failed Levels' directive to client job configuration.
2013-04-08 Russell Harrison rharrison@fedoraproject.org - 0.0.5
- Move CHANGELOG to standard location so it can be found by Puppet Forge
- Fix location of bsmtp utility
2012-11-30 Russell Harrison rharrison@fedoraproject.org - 0.0.4
- Fix MySQL database management
- Specify perms for file resources
- Clean up resource relationships
- Simplify and update documentation
- Migrate
bacula::config::client
tobacula::client::config
- Allow
bacula::client::config
to be called directly to allow configuring clients with exported resources - Proper application of the ASL 2.0
- Move to using fqdn instead of shorter names to simplify management and prevent name collisions
- Stop using scope.lookupvar and allow vars to be passed in as params
- Merge pull request from Erik Smit
- Syntax cleanup
- Move CHANGELOG to Markdown format
- Add Bacula TLS - Communications Encryption management
- Allow mount path of the default backup device to be changed.
- Basic custom FileSet creation
- Include custom config file for the director
- Manage Bacula logwatch configurations
2012-11-25 erik-smit smite@zylon.net
- Allow purging unmanaged files (like outdated clients or filesets) from config-dir.
2012-10-24 erik-smit smite@zylon.net
- Config default plugin directory for file daemon
- Fix bconsole director name (this is NOT Console)
- Fixing catalog support for postgres
- Add Debian/Ubuntu package naming
- Add minimalistic postgres support
2012-09-21 Russell Harrison rharrison@fedoraproject.org
- Moving db management out of common to director and creating subclasses for each backend
2012-09-20 Russell Harrison rharrison@fedoraproject.org
- Changing variables to not be puppet reserved words
- Make sure packages are installed before baclula user and group are defined
Wed Sep 19 2012 Russell Harrison rharrison@fedoraproject.org - 0.0.3
- Documenting this is a fork under my name.
- Simple script to update installed module by hand.
- Modified to work properly with RHEL.
- Remove God aweful global variables. Imposible to maintain.
- Move bacula::config::validate to bacula::params::validate.
- Clean up formating to comply with the style guide.
- Update documentation to reflect changes.
Thu Dec 15 2011 Carl Caum carl@puppetlabs.com - 0.0.2
- Support multiple DB backends
- Support Managing databases through 3rd party modules
- Ability to declare clients through class parameters or ENC variables
- Documentation improvements
Thu Dec 8 2011 Carl Caum carl@puppetlabs.com - 0.0.1
- Manage a Bacula director
- Manage Bacula clients
- Manage a Bacula storage daemon
- Manage console installations
- Customize configuration files with custom templates
Dependencies
- puppetlabs/stdlib (>=2.2.0)
- puppetlabs-mysql (>=1.0.0)
- puppetlabs/sqlite (>=0.0.1)
Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.