nagios
Version information
This version is compatible with:
- ,
Start using this module
Add this module to your Puppetfile:
mod 'jgazeley-nagios', '0.4.0'
Learn more about managing modules with a PuppetfileDocumentation
nagios
Table of Contents
- Overview
- Module Description - What the module does and why it is useful
- Usage - Configuration options and additional functionality
- Examples
- Limitations - OS compatibility, etc.
- Development - Guide for contributing to the module
Overview
This module installs and manages Nagios, NRPE, NSCA, BPI and PNP4Nagios to give you a full monitoring stack.
Module Description
While Nagios itself is not too complex, a full stack installation includes a number of optional components. Let's have a look at the terminology - if you are new to Nagios you should definitely read and understand the definitions before attempting to use this module.
This module is quite opinionated about how Nagios should be set up. I've made it as configurable as I can without deviating from the model that I believe is best, which has been extensively tested in our local environment before publishing. It makes assumptions about how you want to group things that mean you can start benefiting from Nagios quickly without having to set too much up.
This module makes heavy use of Puppet exported resources to configure Nagios. You must have a working Puppet and PuppetDB environment with exported resources before using this module.
Warning: This module uses puppetlabs/apache
to configure the web frontend. Be aware that puppetlabs/apache
will purge all other Apache config that is not managed with puppetlabs/apache
. This Nagios module with play nicely with other web sites configured with apache::vhost
but it will break anything else that has been configured manually.
Nagios
Nagios is the name of the main monitoring application, and it includes a web application and a backend daemon. The daemon does the actual monitoring by executing plugins which send probes to clients, and then displaying the results in the web application or sending them via notifications.
Be careful with the terminology: here we use server to refer to the Nagios server, and client to refer to the Nagios clients, even though they may be servers in their own right.
+--------+ +--------+
| Nagios | ---> | Client |
+--------+ +--------+
NRPE
While Nagios is good at sending probes to clients that are offering services (e.g. sending HTTP requests to web servers) it needs something extra to probe non-public aspects of a client, e.g. checking CPU usage.
To achieve this, we run the NRPE daemon on the client which listens for the server and executes plugins to probe the local system. The Nagios server probes NRPE on the client which runs the plugin and returns the result to Nagios.
+--------+ +--------+ +--------+
| Nagios | ---> | NRPE | ---> | Client |
+--------+ +--------+ +--------+
NSCA
NSCA works the other way round from NRPE. NSCA runs on the server and listens for clients to submit passive checks to Nagios on their own schedule (e.g. via cron) rather than the Nagios server initiating the probes.
+--------+ +--------+ +--------+
| Nagios | <--- | NSCA | <--- | Client |
+--------+ +--------+ +--------+
BPI
BPI (Business Process Intelligence) is an addon for Nagios which is able to model real-world applications based on a set of probes. For example: you may have a cluster of 2 web servers and so long as either server is up, the overall service is up. You might not care if only one server is down. BPI uses logic like this to work out if your real services are up or down and send appropriate alerts.
PNP4Nagios
Some Nagios plugins return performance data as well as a status code. Out of the box, Nagios can't do anything with this data, but PNP4Nagios can process this data with RRD and automatically draw graphs.
Usage
This module is designed so the base class ::nagios
configures a Nagios monitoring server. Other classes are available such as ::nagios::client
which configures a Nagios client to be monitored. There are also some defined types which should be directly called where necessary to configure extras.
Classes
::nagios
The ::nagios
class installs a Nagios monitoring server and related components.
client
Install components to run a Nagios client, i.e. a server that is monitored. Default: true
server
Install components to run a Nagios monitoring server. Default: false
nrpe
Install support for NRPE, which is required if you want to execute Nagios checks on remote servers (clients). Default: false
nsca
Install support for NSCA, which is required if you want to execute passive Nagios checks. Default: false
selinux
Manage SELinux rules to allow Nagios components to run properly on the clients and server. Strongly recommended if you are running a Red Hat family distro, and SELinux is enabled on your system. Requires puppet/selinux
. Default: false
firewall
Manage firewall rules on Nagios clients and server. Strongly recommended to allow Nagios components to work properly. Caution: firewall rules are managed by puppetlabs/firewall
. That module purges any firewall rules that are not managed with puppetlabs/firewall
so be extremely careful before enabling this option. Default: false
url
Override the hostname that your Nagios server will run on, if you don't want it to run on the server's $::fqdn
. Default: $::fqdn
aliases
Array of alternative hostnames that your Nagios server should respond to. Don't forget to set these as alternate names in your SSL certificate. Default: []
dev
Set a flag to mark this Nagios server as a development/testing server. This suppresses active notifications from Nagios. Default: false
serveradmin
Server admin email address for use by Apache. Default: root@localhost
notify_admin
Whether to send Nagios host and service notifications to $serveradmin
. Default: false
auto_os_hostgroup
Whether to automatically add this client to a hostgroup of its OS type. Default: true
auto_virt_hostgroup
Whether to automatically add this client to a hostgroup of its hardware/virtualised platform. Default: true
hostgroups
Array of other hostgroups to add the system to. Default: []
parent
Name of a parent object. Default: undef
alias
Set alias for a host. Default: undef
nrpe_package
Name of the NRPE package. You shouldn't need to override this. If you need to add support for a new distro, please send a pull request or raise an issue.
webroot
Location of the webroot on the filesystem. If you need to add support for a new distro, please send a pull request or raise an issue.
cgiroot
Location of the CGI root on the filesystem. If you need to add support for a new distro, please send a pull request or raise an issue.
nsca_client_package
Name of the NSCA client package. If you need to add support for a new distro, please send a pull request or raise an issue.
nrpe_service
Name of the NRPE service. If you need to add support for a new distro, please send a pull request or raise an issue.
nrpe_config
Path to the NRPE config file. If you need to add support for a new distro, please send a pull request or raise an issue.
nrpe_d
Path to the NRPE conf.d directory. If you need to add support for a new distro, please send a pull request or raise an issue.
nrpe_plugin_package
Name of the NRPE plugin package. If you need to add support for a new distro, please send a pull request or raise an issue.
nsca_server_package
Name of the NSCA server package. If you need to add support for a new distro, please send a pull request or raise an issue.
nsca_service
Name of the NSCA service. If you need to add support for a new distro, please send a pull request or raise an issue.
nsca_config
Path to the NSCA config file. If you need to add support for a new distro, please send a pull request or raise an issue.
nagios_package
Name of the Nagios package. If you need to add support for a new distro, please send a pull request or raise an issue.
nagios_service
Name of the Nagios service. If you need to add support for a new distro, please send a pull request or raise an issue.
::nagios::client
The ::nagios::client
class installs components needed for a system to be monitored by a Nagios monitoring server.
nrpe
Whether to enable support for NRPE. Default: true
nsca
Whether to enable support for NSCA. Default: true
selinux
Whether to manage SELinux policies to allow plugins to execute properly via NRPE. Default: true
firewall
Whether to manage firewall rules to allow plugin to execute properly via NRPE. Default: true
basic_checks
Whether to set up a basic set of checks that should work on all systems (e.g. ping). Default: true
nrpe_package
Name of the NRPE client package. If you need to add support for a new distro, please send a pull request or raise an issue.
nsca_client_package
Name of the NSCA client package. If you need to add support for a new distro, please send a pull request or raise an issue.
nrpe_service
Name of the NRPE service. If you need to add support for a new distro, please send a pull request or raise an issue.
nrpe_config
Path to the NRPE config file. If you need to add support for a new distro, please send a pull request or raise an issue.
nrpe_d
Path to the NRPE conf.d directory. If you need to add support for a new distro, please send a pull request or raise an issue.
nrpe_plugin_package
Name of the NRPE plugin package. If you need to add support for a new distro, please send a pull request or raise an issue.
ssl_cert
Path to SSL server certificate. Default: /path/to/cert.crt
ssl_key
Path to SSL private key. Default: /path/to/key.key
ssl_chain
Path to SSL certificate chain file. Default: undef
ssl_cipher
Allowed SSL ciphers. Defaults to a more secure list than ships with puppetlabs/apache
. Default: HIGH:!MEDIUM:!aNULL:!MD5:!RC4:!3DES
Defined types
nagios::service
The ::nagios::service
defined type installs a service, a command and other related components required to monitor something.
host_name
Hostname of the system that the check should be associated with. Default: $::fqdn
check_command
Override the name of the check command in the service definition. Default: $title
service_description
Human-readable name for the service.
use
Name of the Nagios template to inherit from. Default: undef
servicegroups
One or more additional servicegroups that this service should be a member of. It will automatically be added to a
servicegroup with the same name as the check. Default: undef
add_servicegroup
Whether to automatically create the servicegroup that this service belongs to by default. Default: true
add_servicedep
Whether to automatically add a service dependency on NRPE, if this service is a NRPE-based check. Default: true
active_checks_enabled
Whether to override active checks. Default: undef
max_check_attempts
Whether to override the maximum number of check attempts before reporting hard state. Default: undef
check_freshness
Override check freshness. Probably only useful for passive checks. Default: undef
freshness_threshold
Override freshness threshold. Probably only useful for passive checks. Default: undef
command_definition
The command line used to execute the plugin. The default can be used only if no arguments are required. Default: $check_command
check_interval
Override the check interval on a per-service basis. This is usually inherited from a template with use
. Default: undef
use_nrpe
Whether to execute this check on the monitored host via NRPE. Default: false
use_sudo
Whether to use sudo when executing this check. Default: false
sudo_user
The username to use when executing plugins with sudo when $use_sudo = true
. Default undef
install_plugin
Whether to install the Nagios plugin on the system. Default: true
plugin_provider
Provider for the plugin installation, if $install_plugin = true
. Default: package
plugin_source
Source for installation of the plugin if $install_plugin = true
. Default: undef
service_dependency
Add arbitrary service dependencies on other services on this host. Default: undef
nagios_server
The hostname of the Nagios server that will be monitoring this host. Default: hiera('nagios_server')
nagios::bpi::config
The ::nagios::bpi::config
defined type configures a BPI "service", i.e. a group or one or more
monitored objects in Nagios. The title of this resource forms the BPI groupID and must be alphanumeric
characters with no spaces. This ID is used internally by the program as well as for the check_bpi.php
plugin.
This can be a bit confusing to configure, especially the members
option, so it is probably
best to read the examples below.
# Group of DNS servers created by checking the `DNS` Nagios service on all DNS servers.
# If one or more DNS servers is up, this group counts as up.
nagios::bpi::config { 'dns':
displayname => 'DNS',
members => [
{
host => 'dns1.example.com',
service => 'DNS',
opt => '&',
},
{
host => 'dns2.example.com',
service => 'DNS',
opt => '&',
},
],
priority => 2,
primary => 0,
}
# Group of DHCP servers created by checking the `DHCP` Nagios service on all DHCP servers.
# If one or more DHCP servers is up, this group counts as up.
nagios::bpi::config { 'dhcp':
displayname => 'DHCP',
members => [
{
host => 'dhcp1.example.com',
service => 'DHCP',
opt => '&',
},
{
host => 'dhcp2.example.com',
service => 'DHCP',
opt => '&',
},
],
priority => 2,
primary => 0,
}
# Virtual group to reflect the state of the whole network. If the DNS and DHCP groups
# are both up, this group is up. If either DNS or DHCP is down, this group is down.
nagios::bpi::config { 'network':
displayname => 'Network',
members => [
{
host => '$dns',
opt => '|',
},
{
host => '$dhcp',
opt => '|',
},
],
priority => 1,
primary => 1,
}
displayname
The display name for the BPI group (required)
members
Members of this BPI group, which can consist or services and other BPI groups. Data should be expressed as an array of hashes with the following keys:
host
: The hostname of a host in Nagios or the groupID of a BPI group. Required.service
: The servicename of a service in Nagios, ifhost
is a Nagios host. Not required ifhost
is a BPI group.opt
: an&
or|
character where&
means service is part of a cluster and|
means it is an essential service for the group.
For example: a critical service with an |
option will cause a critical state for the entire group.
For clusters, critical is only reached when ALL services in a cluster are NOT OK.
nagios
Automatically create a Nagios check for this BPI group. Default: true
desc
Description for a bpi group. Optional, default: undef
primary
Primary/Top-Level groups are 1
, subgroups are 0
. Setting 0
hides the BPI group except where is explicitly
referenced as a component of another BPI group. Default: 1
info
Link to internal or external webpage. Optional, default: undef
warning_threshold
The number of problems a group reaches before going 'warning'. Default: 0
critical_threshold
The number of problems a group reaches before going 'critical'. Default: 0
priority
The display priority on screen between 1-3
, 1
being 'high priority'. Default: 1
event_handler
Set an event handler for this BPI group's Nagios check. Only makes sense if nagios=true
. Default: undef
uptime_report
Enable periodic email reports about uptime of BPI services. Choose from yesterday
, lastweek
,
lastmonth
, lastyear
. Default: undef
uptime_report_recipients
One or more email addresses who should receive the uptime report. Mus be expressed as an array
even if there is only one email address. Default: $serveradmin
Examples
Install a Nagios server
class ::profile::nagios {
# Install Nagios server
class { 'nagios':
nrpe => true, # Set up NRPE for monitoring of remote hosts
nsca => false, # Skip NSCA, which is needed for passive checks
selinux => true, # Manage SELinux policies to allow Nagios to run smoothly
firewall => true, # Manage firewall rules to allow Nagios/NRPE to run smoothly
url => 'nagios.example.com', # Service URL of Nagios, if different from the system hostname
serveradmin => 'root@example.com', # Admin's email address
ssl_cert => '/etc/pki/tls/certs/nagios.example.com.pem', # Path to SSL cert for HTTPS
ssl_key => '/etc/pki/tls/private/nagios.example.com.key', # Path to SSL key for HTTPS
auth_type => 'CAS', # Override Apache basic auth and use CAS single sign-on instead
}
# Deploy HTTPS certificate
file { '/etc/pki/tls/certs/nagios.example.com.pem':
source => 'puppet:///modules/profile/nagios/nagios.example.com.pem',
mode => '0644',
owner => 'root',
group => 'root',
}
# Deploy HTTPS private key
file { '/etc/pki/tls/private/nagios.example.com.key':
source => 'puppet:///modules/profile/nagios/nagios.example.com.key',
mode => '0600',
owner => 'root',
group => 'root',
}
}
Basic non-NRPE service
This service definition monitors the host remotely, directly from the Nagios server. This is ideal for monitoring services that are available on the remote host, such as HTTP.
nagios::service { 'check_http':
service_description => 'HTTP',
plugin_source => 'nagios-plugins-http',
command_definition => 'check_http -I $HOSTADDRESS$ $ARG1$',
}
Basic NRPE service
This service definition installs the plugin on the monitored host and configures NRPE. The check itself is installed on the Nagios server. This is ideal for monitoring attributes of the remote host that are not available externally.
nagios::service { 'check_users':
use_nrpe => true, # Execute this on the host via NRPE
service_description => 'Current users', # Human-readable description
plugin_source => 'nagios-plugins-users', # Package that provides this plugin
command_definition => 'check_users -w 10 -c 20', # Syntax for actually calling the plugin
}
Service running on an unmanaged host
This service definition is applied to the Nagios server, and the host name is overridden to point at a different system (one that is not managed by Puppet). This is ideal for monitoring "dumb" devices such as switches or other people's servers that you have no access to.
nagios::service { 'check_ping_router':
host_name => 'router.example.com',
plugin_source => 'nagios-plugins-ping',
service_description => 'Ping',
command_definition => 'check_ping -H $HOSTADDRESS$ -w 100,10% -c 1000,50% -p 5',
}
Service running on a manually managed host
This service definition is applied to the Nagios server and the host name is overriden to point at a different system which is manually managed, and has a manually-configured NRPE agent but no Puppet agent. This is ideal for monitoring legacy servers where you can't retrofit Puppet.
nagios::service { 'check_load_legacysystem.example.com':
check_command => 'check_load', # Name of the command we have manually set on the remote system
use_nrpe => true, # Use NRPE, which we have manually set up
service_description => 'Load',
host_name => 'legacysystem.example.com', # Override monitored server name
install_plugin => false, # Don't attempt to manage the plugin
}
Limitations
This module has been developed for Nagios 4 on CentOS 7. It's pretty flexible so it should work on other platforms too but they have had little-to-no testing.
This module is currently functional but not feature-complete. There are rough edges and things not implemented yet. Please look at the issue tracker to look for outstanding issues and feature requests.
In particular the HTTPS/SSL config is rough around the edges and quite a few options are hard-coded in and need to be brought out to parameters.
Development
This module was written initially for internal use - features we haven't needed to use probably haven't been written. Please send pull requests with new features and bug fixes. You are also welcome to file issues but I make no guarantees of development effort if the features aren't useful to my employer.
Changelog
0.4.0
- Add support for periodic uptime notifications
0.3.3
- Fix bug with duplicate servicegroups
0.3.2
- Default disable notifications being sent to the serveradmin
0.3.1
- Expose alias as a settable parameter
0.3.0
- Re-jig BPI groups
0.2.0
- Make automatic hostgroups optional
- Allow manual override of hostgroups
- Expose parent as a settable parameter
0.1.0
- First release, functional and stable but not yet feature-complete
Dependencies
- puppetlabs-stdlib (>= 4.0.0 < 5.0.0)
- puppetlabs/concat (>= 4.0.0 < 5.0.0)
- puppet/selinux (>= 1.0.0 < 2.0.0)
- puppetlabs/firewall (>= 1.9.0 < 2.0.0)
- puppetlabs/vcsrepo (>= 2.0.0 < 3.0.0)
- puppetlabs/apache (>= 1.0.0 < 2.0.0)
- stahnma/epel (>= 1.0.0 < 2.0.0)
- saz/sudo (>= 4.0.0 < 5.0.0)
- dalen/dnsquery (>= 3.0.0 < 4.0.0)
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.