]> git.openstreetmap.org Git - chef.git/commitdiff
Merge branch 'patch-2' of https://github.com/Tigerfell/chef into pr257
authorTigerfell <tigerfell-688@tuta.io>
Tue, 9 Mar 2021 18:29:53 +0000 (19:29 +0100)
committerTigerfell <tigerfell-688@tuta.io>
Tue, 9 Mar 2021 18:29:53 +0000 (19:29 +0100)
850 files changed:
.editorconfig [new file with mode: 0644]
.github/dependabot.yml [new file with mode: 0644]
.github/workflows/cookstyle.yml [new file with mode: 0644]
.github/workflows/test-kitchen.yml [new file with mode: 0644]
.gitignore
.kitchen.provision.rb [deleted file]
.kitchen.yml
.mailmap
.rubocop.yml
.rubocop_todo.yml
.ruby-version
.travis.yml [deleted file]
Dockerfile
Gemfile
Gemfile.lock
README.md
cookbooks/accounts/attributes/default.rb
cookbooks/accounts/files/default/dmlu/.ssh/authorized_keys [new file with mode: 0644]
cookbooks/accounts/files/default/grant/.gitconfig [new file with mode: 0644]
cookbooks/accounts/recipes/default.rb
cookbooks/apache/attributes/default.rb
cookbooks/apache/metadata.rb
cookbooks/apache/recipes/default.rb
cookbooks/apache/resources/conf.rb
cookbooks/apache/resources/module.rb
cookbooks/apache/resources/site.rb
cookbooks/apache/templates/default/httpd.conf.erb
cookbooks/apache/templates/default/ssl.erb
cookbooks/apt/attributes/default.rb
cookbooks/apt/recipes/default.rb
cookbooks/apt/templates/default/apt.conf.erb
cookbooks/apt/templates/default/sources.list.erb
cookbooks/backup/attributes/default.rb
cookbooks/backup/metadata.rb
cookbooks/backup/recipes/default.rb
cookbooks/backup/templates/default/expire.cron.erb
cookbooks/bind/recipes/default.rb
cookbooks/blog/recipes/default.rb
cookbooks/blog/templates/default/backup.cron.erb
cookbooks/blogs/metadata.rb
cookbooks/blogs/recipes/default.rb
cookbooks/blogs/templates/default/blogs-update.erb [new file with mode: 0644]
cookbooks/blogs/templates/default/cron.erb [deleted file]
cookbooks/cgiirc/README.md [deleted file]
cookbooks/cgiirc/templates/default/cgiirc.config.erb [deleted file]
cookbooks/cgiirc/templates/default/ipaccess.erb [deleted file]
cookbooks/chef/attributes/default.rb
cookbooks/chef/libraries/git.rb [new file with mode: 0644]
cookbooks/chef/libraries/persistent_token.rb [new file with mode: 0644]
cookbooks/chef/libraries/subversion.rb
cookbooks/chef/recipes/default.rb
cookbooks/chef/recipes/repository.rb
cookbooks/chef/recipes/server.rb
cookbooks/chef/templates/default/chef-client.conf.erb [deleted file]
cookbooks/chef/templates/default/client.rb.erb
cookbooks/chef/templates/default/report.rb.erb
cookbooks/chef/templates/default/server-backup.cron.erb
cookbooks/civicrm/attributes/default.rb
cookbooks/civicrm/recipes/default.rb
cookbooks/civicrm/templates/default/backup.cron.erb
cookbooks/civicrm/templates/default/cron.erb [deleted file]
cookbooks/clamav/recipes/default.rb
cookbooks/db/attributes/default.rb [new file with mode: 0644]
cookbooks/db/metadata.rb
cookbooks/db/recipes/backup.rb
cookbooks/db/recipes/base.rb
cookbooks/db/recipes/master.rb
cookbooks/db/templates/default/backup.cron.erb [deleted file]
cookbooks/db/templates/default/wal-e.erb
cookbooks/dev/files/default/ooc/index.html
cookbooks/dev/metadata.rb
cookbooks/dev/recipes/default.rb
cookbooks/dev/templates/default/apache.phppgadmin.erb
cookbooks/dev/templates/default/apache.rails.erb
cookbooks/dev/templates/default/apache.user.erb
cookbooks/dev/templates/default/fpm-default.conf.erb [deleted file]
cookbooks/dev/templates/default/fpm.conf.erb [deleted file]
cookbooks/devices/recipes/default.rb
cookbooks/devices/templates/default/udev.rules.erb
cookbooks/dhcpd/metadata.rb
cookbooks/dhcpd/recipes/default.rb
cookbooks/dhcpd/templates/default/dhcpd.conf.erb
cookbooks/dmca/files/default/html/index.php
cookbooks/dmca/metadata.rb
cookbooks/dmca/recipes/default.rb
cookbooks/dmca/templates/default/apache.erb
cookbooks/dns/attributes/default.rb [new file with mode: 0644]
cookbooks/dns/metadata.rb
cookbooks/dns/recipes/default.rb
cookbooks/dns/templates/default/creds.json.erb [new file with mode: 0644]
cookbooks/dns/templates/default/dns-check.erb
cookbooks/dns/templates/default/dns-update.erb
cookbooks/dns/templates/default/zone.html.erb
cookbooks/docker/attributes/default.rb [new file with mode: 0644]
cookbooks/docker/metadata.rb [moved from cookbooks/openvpn/metadata.rb with 61% similarity]
cookbooks/docker/recipes/default.rb [new file with mode: 0644]
cookbooks/docker/templates/default/daemon.json.erb [new file with mode: 0644]
cookbooks/donate/attributes/default.rb [new file with mode: 0644]
cookbooks/donate/metadata.rb
cookbooks/donate/recipes/default.rb
cookbooks/donate/templates/default/apache.erb
cookbooks/donate/templates/default/backup.cron.erb
cookbooks/donate/templates/default/cron.erb [deleted file]
cookbooks/elasticsearch/attributes/default.rb
cookbooks/elasticsearch/metadata.rb
cookbooks/elasticsearch/recipes/default.rb
cookbooks/exim/attributes/default.rb
cookbooks/exim/metadata.rb
cookbooks/exim/recipes/default.rb
cookbooks/exim/templates/default/apache-mta-sts.erb [new file with mode: 0644]
cookbooks/exim/templates/default/default.erb [new file with mode: 0644]
cookbooks/exim/templates/default/dkim-domains.erb [new file with mode: 0644]
cookbooks/exim/templates/default/dkim-selectors.erb [new file with mode: 0644]
cookbooks/exim/templates/default/exim4.conf.erb
cookbooks/exim/templates/default/mta-sts.erb [new file with mode: 0644]
cookbooks/fail2ban/metadata.rb
cookbooks/fail2ban/recipes/default.rb
cookbooks/fail2ban/resources/filter.rb
cookbooks/fail2ban/resources/jail.rb
cookbooks/fail2ban/templates/default/paths-overrides.local.erb [moved from cookbooks/dns/templates/default/cron.erb with 57% similarity]
cookbooks/forum/attributes/default.rb [new file with mode: 0644]
cookbooks/forum/metadata.rb
cookbooks/forum/recipes/default.rb
cookbooks/forum/templates/default/apache.erb
cookbooks/forum/templates/default/backup.cron.erb
cookbooks/foundation/recipes/board.rb
cookbooks/foundation/recipes/dwg.rb
cookbooks/foundation/recipes/mwg.rb
cookbooks/foundation/recipes/owg.rb
cookbooks/foundation/recipes/wiki.rb
cookbooks/ftp/recipes/default.rb
cookbooks/geodns/metadata.rb
cookbooks/geodns/recipes/default.rb
cookbooks/geodns/templates/default/config.erb
cookbooks/geodns/templates/default/geo.erb
cookbooks/geodns/templates/default/zone.map.erb [new file with mode: 0644]
cookbooks/geodns/templates/default/zone.resource.erb [new file with mode: 0644]
cookbooks/geodns/templates/default/zone.weighted.erb [new file with mode: 0644]
cookbooks/geoipupdate/README.md [new file with mode: 0644]
cookbooks/geoipupdate/attributes/default.rb [new file with mode: 0644]
cookbooks/geoipupdate/metadata.rb [new file with mode: 0644]
cookbooks/geoipupdate/recipes/default.rb [new file with mode: 0644]
cookbooks/geoipupdate/templates/default/GeoIP.conf.erb [new file with mode: 0644]
cookbooks/git/attributes/default.rb
cookbooks/git/metadata.rb
cookbooks/git/recipes/default.rb
cookbooks/git/recipes/server.rb
cookbooks/git/recipes/web.rb
cookbooks/git/templates/default/apache.erb
cookbooks/git/templates/default/backup.cron.erb
cookbooks/gps-tile/attributes/default.rb [new file with mode: 0644]
cookbooks/gps-tile/files/default/html/index.html
cookbooks/gps-tile/metadata.rb
cookbooks/gps-tile/recipes/default.rb
cookbooks/hardware/attributes/default.rb
cookbooks/hardware/metadata.rb
cookbooks/hardware/recipes/default.rb
cookbooks/hardware/templates/default/ipmi_local.yml.erb [new file with mode: 0644]
cookbooks/hardware/templates/default/irqbalance.erb [deleted file]
cookbooks/hardware/templates/default/ohai.rb.erb
cookbooks/hardware/templates/default/smart.devices.erb [new file with mode: 0644]
cookbooks/hardware/templates/default/update-smart-drivedb.erb [new file with mode: 0644]
cookbooks/imagery/files/default/os-openmap-local-palette.txt [new file with mode: 0644]
cookbooks/imagery/recipes/default.rb
cookbooks/imagery/recipes/gb_os_sv.rb
cookbooks/imagery/recipes/lu_lidar_hillshade.rb [new file with mode: 0644]
cookbooks/imagery/recipes/lu_ngl_dtm.rb [new file with mode: 0644]
cookbooks/imagery/resources/layer.rb
cookbooks/imagery/resources/site.rb
cookbooks/imagery/templates/default/imagery.js.erb
cookbooks/imagery/templates/default/index.html.erb
cookbooks/imagery/templates/default/mapserver.map.erb
cookbooks/imagery/templates/default/nginx_default.conf.erb
cookbooks/imagery/templates/default/nginx_imagery.conf.erb
cookbooks/imagery/templates/default/nginx_imagery_layer_fragment.conf.erb
cookbooks/incron/recipes/default.rb
cookbooks/irc/README.md [new file with mode: 0644]
cookbooks/irc/files/default/html/index.html [new file with mode: 0644]
cookbooks/irc/files/default/html/style.css [new file with mode: 0644]
cookbooks/irc/metadata.rb [moved from cookbooks/cgiirc/metadata.rb with 72% similarity]
cookbooks/irc/recipes/default.rb [moved from cookbooks/cgiirc/recipes/default.rb with 77% similarity]
cookbooks/irc/templates/default/apache.erb [moved from cookbooks/cgiirc/templates/default/apache.erb with 60% similarity]
cookbooks/kibana/attributes/default.rb
cookbooks/kibana/metadata.rb
cookbooks/kibana/recipes/default.rb
cookbooks/letsencrypt/attributes/default.rb [new file with mode: 0644]
cookbooks/letsencrypt/files/default/bin/check-certificate
cookbooks/letsencrypt/files/default/bin/renew
cookbooks/letsencrypt/metadata.rb
cookbooks/letsencrypt/recipes/default.rb
cookbooks/letsencrypt/templates/default/cron.erb [deleted file]
cookbooks/letsencrypt/templates/default/logrotate.erb [new file with mode: 0644]
cookbooks/letsencrypt/templates/default/request.erb
cookbooks/logstash/attributes/default.rb
cookbooks/logstash/metadata.rb
cookbooks/logstash/recipes/default.rb
cookbooks/logstash/recipes/forwarder.rb
cookbooks/mailman/metadata.rb
cookbooks/mailman/recipes/default.rb
cookbooks/mailman/templates/default/backup.cron.erb
cookbooks/mailman/templates/default/mm_cfg.py.erb
cookbooks/mediawiki/attributes/default.rb
cookbooks/mediawiki/metadata.rb
cookbooks/mediawiki/recipes/default.rb
cookbooks/mediawiki/resources/extension.rb
cookbooks/mediawiki/resources/site.rb
cookbooks/mediawiki/resources/skin.rb
cookbooks/mediawiki/templates/default/LocalSettings.php.erb
cookbooks/mediawiki/templates/default/apache.erb
cookbooks/mediawiki/templates/default/mediawiki-backup.cron.erb
cookbooks/mediawiki/templates/default/mediawiki.cron.erb [deleted file]
cookbooks/mediawiki/templates/default/mw-ext-AbuseFilter.inc.php.erb
cookbooks/mediawiki/templates/default/mw-ext-CirrusSearch.inc.php.erb
cookbooks/mediawiki/templates/default/mw-ext-SlippyMap.inc.php.erb [deleted file]
cookbooks/memcached/metadata.rb
cookbooks/memcached/recipes/default.rb
cookbooks/memcached/templates/default/memcached.conf.erb
cookbooks/munin/files/default/plugins/api_calls_
cookbooks/munin/files/default/plugins/api_waits_
cookbooks/munin/recipes/default.rb
cookbooks/munin/recipes/plugins.rb [new file with mode: 0644]
cookbooks/munin/recipes/server.rb
cookbooks/munin/resources/plugin.rb
cookbooks/munin/resources/plugin_conf.rb
cookbooks/munin/templates/default/apache.erb
cookbooks/munin/templates/default/backup.cron.erb
cookbooks/munin/templates/default/munin-node.conf.erb
cookbooks/munin/templates/default/munin.conf.erb
cookbooks/mysql/libraries/mysql.rb
cookbooks/mysql/metadata.rb
cookbooks/mysql/recipes/default.rb
cookbooks/mysql/resources/database.rb
cookbooks/mysql/resources/user.rb
cookbooks/networking/attributes/default.rb
cookbooks/networking/definitions/firewall_rule.rb [deleted file]
cookbooks/networking/libraries/ipaddresses.rb
cookbooks/networking/metadata.rb
cookbooks/networking/recipes/default.rb
cookbooks/networking/resources/firewall_rule.rb [new file with mode: 0644]
cookbooks/networking/templates/default/hostname.erb [deleted file]
cookbooks/networking/templates/default/resolved.conf.erb
cookbooks/networking/templates/default/shorewall-interfaces.erb
cookbooks/networking/templates/default/shorewall-zones.erb
cookbooks/networking/templates/default/wireguard.netdev.erb [new file with mode: 0644]
cookbooks/networking/templates/default/wireguard.network.erb [new file with mode: 0644]
cookbooks/nfs/attributes/default.rb [new file with mode: 0644]
cookbooks/nfs/recipes/default.rb
cookbooks/nfs/recipes/server.rb
cookbooks/nginx/attributes/default.rb
cookbooks/nginx/metadata.rb
cookbooks/nginx/recipes/default.rb
cookbooks/nginx/resources/site.rb
cookbooks/nginx/templates/default/munin.erb [new file with mode: 0644]
cookbooks/nginx/templates/default/nginx-old-cache-cleanup.erb [new file with mode: 0644]
cookbooks/nginx/templates/default/nginx.conf.erb
cookbooks/nodejs/resources/package.rb
cookbooks/nominatim/attributes/default.rb
cookbooks/nominatim/metadata.rb
cookbooks/nominatim/recipes/default.rb
cookbooks/nominatim/templates/default/apache.erb [deleted file]
cookbooks/nominatim/templates/default/fpm.conf.erb [deleted file]
cookbooks/nominatim/templates/default/git-post-merge-hook.erb
cookbooks/nominatim/templates/default/logrotate.nginx.erb [moved from cookbooks/nominatim/templates/default/logrotate.apache.erb with 50% similarity]
cookbooks/nominatim/templates/default/logrotate.nominatim.erb
cookbooks/nominatim/templates/default/nginx.erb [new file with mode: 0644]
cookbooks/nominatim/templates/default/nominatim.cron.erb [deleted file]
cookbooks/nominatim/templates/default/nominatim.env.erb [new file with mode: 0644]
cookbooks/nominatim/templates/default/settings.erb [deleted file]
cookbooks/nominatim/templates/default/ui-config.js.erb [new file with mode: 0644]
cookbooks/nominatim/templates/default/updater.erb
cookbooks/ntp/metadata.rb
cookbooks/ntp/recipes/default.rb
cookbooks/ntp/templates/default/chrony.conf.erb
cookbooks/ohai/resources/plugin.rb
cookbooks/openssh/recipes/default.rb
cookbooks/openssh/templates/default/ssh_config.erb [deleted file]
cookbooks/openssh/templates/default/ssh_known_hosts.erb
cookbooks/openssh/templates/default/sshd_config.conf.erb [moved from cookbooks/web/templates/default/statistics.cron.erb with 56% similarity]
cookbooks/openvpn/README.md [deleted file]
cookbooks/openvpn/attributes/default.rb [deleted file]
cookbooks/openvpn/recipes/default.rb [deleted file]
cookbooks/openvpn/templates/default/tunnel.conf.erb [deleted file]
cookbooks/osmosis/attributes/default.rb
cookbooks/osmosis/recipes/default.rb
cookbooks/osqa/attributes/default.rb
cookbooks/osqa/metadata.rb
cookbooks/osqa/recipes/default.rb
cookbooks/osqa/templates/default/apache.erb
cookbooks/osqa/templates/default/backup.cron.erb
cookbooks/otrs/attributes/default.rb
cookbooks/otrs/metadata.rb
cookbooks/otrs/recipes/default.rb
cookbooks/otrs/templates/default/backup.cron.erb
cookbooks/passenger/attributes/default.rb
cookbooks/passenger/metadata.rb
cookbooks/passenger/recipes/default.rb
cookbooks/passenger/resources/application.rb
cookbooks/php/README.md [new file with mode: 0644]
cookbooks/php/attributes/default.rb [new file with mode: 0644]
cookbooks/php/metadata.rb [moved from cookbooks/roundup/metadata.rb with 66% similarity]
cookbooks/php/recipes/apache.rb [new file with mode: 0644]
cookbooks/php/recipes/default.rb [moved from cookbooks/roundup/recipes/default.rb with 83% similarity]
cookbooks/php/recipes/fpm.rb [new file with mode: 0644]
cookbooks/php/resources/fpm.rb [new file with mode: 0644]
cookbooks/php/templates/default/php-fpm.ini.erb [new file with mode: 0644]
cookbooks/php/templates/default/pool.conf.erb [new file with mode: 0644]
cookbooks/piwik/attributes/default.rb
cookbooks/piwik/metadata.rb
cookbooks/piwik/recipes/default.rb
cookbooks/piwik/templates/default/apache.erb
cookbooks/piwik/templates/default/config.erb
cookbooks/piwik/templates/default/cron.erb [deleted file]
cookbooks/planet/attributes/default.rb
cookbooks/planet/files/default/ccbysa_history_cgi/HEADER.cgi
cookbooks/planet/files/default/cgi/HEADER.cgi
cookbooks/planet/files/default/history_cgi/HEADER.cgi
cookbooks/planet/files/default/html/robots.txt
cookbooks/planet/files/default/html/style.css
cookbooks/planet/files/default/replication-bin/replicate-changesets
cookbooks/planet/files/default/replication-cgi/HEADER.cgi
cookbooks/planet/metadata.rb
cookbooks/planet/recipes/current.rb
cookbooks/planet/recipes/default.rb
cookbooks/planet/recipes/dump.rb
cookbooks/planet/recipes/notes.rb
cookbooks/planet/recipes/replication.rb
cookbooks/planet/templates/default/apache.erb
cookbooks/planet/templates/default/changesets.conf.erb
cookbooks/planet/templates/default/old-planet-file-cleanup.cron.erb [deleted file]
cookbooks/planet/templates/default/planet-dump-mirror-cron.erb [deleted file]
cookbooks/planet/templates/default/planet-mirror-redirect-update.erb
cookbooks/planet/templates/default/planet-notes-dump.cron.erb [deleted file]
cookbooks/planet/templates/default/planet-notes-dump.erb
cookbooks/planet/templates/default/planet-update-file.erb
cookbooks/planet/templates/default/planetdump.erb
cookbooks/planet/templates/default/replicate-minute.erb [new file with mode: 0644]
cookbooks/planet/templates/default/replication.cron.erb [deleted file]
cookbooks/planet/templates/default/streaming.init.erb [deleted file]
cookbooks/postgresql/attributes/default.rb
cookbooks/postgresql/metadata.rb
cookbooks/postgresql/recipes/default.rb
cookbooks/postgresql/resources/database.rb
cookbooks/postgresql/resources/execute.rb
cookbooks/postgresql/resources/extension.rb
cookbooks/postgresql/resources/munin.rb
cookbooks/postgresql/resources/table.rb
cookbooks/postgresql/resources/tablespace.rb
cookbooks/postgresql/resources/user.rb
cookbooks/postgresql/templates/default/postgres_queries.yml.erb [new file with mode: 0644]
cookbooks/postgresql/templates/default/postgresql.conf.erb
cookbooks/prometheus/README.md [new file with mode: 0644]
cookbooks/prometheus/attributes/default.rb [new file with mode: 0644]
cookbooks/prometheus/metadata.rb [new file with mode: 0644]
cookbooks/prometheus/recipes/default.rb [new file with mode: 0644]
cookbooks/prometheus/recipes/server.rb [new file with mode: 0644]
cookbooks/prometheus/resources/collector.rb [new file with mode: 0644]
cookbooks/prometheus/resources/exporter.rb [new file with mode: 0644]
cookbooks/prometheus/templates/default/alert_rules.yml.erb [new file with mode: 0644]
cookbooks/prometheus/templates/default/alertmanager.yml.erb [new file with mode: 0644]
cookbooks/prometheus/templates/default/amtool.yml.erb [moved from cookbooks/planet/templates/default/planet-update.cron.erb with 50% similarity]
cookbooks/prometheus/templates/default/apache.erb [new file with mode: 0644]
cookbooks/prometheus/templates/default/backup.cron.erb [new file with mode: 0644]
cookbooks/prometheus/templates/default/chef.prom.erb [new file with mode: 0644]
cookbooks/prometheus/templates/default/default.alertmanager.erb [new file with mode: 0644]
cookbooks/prometheus/templates/default/default.prometheus.erb [new file with mode: 0644]
cookbooks/prometheus/templates/default/grafana.ini.erb [new file with mode: 0644]
cookbooks/prometheus/templates/default/prometheus.yml.erb [new file with mode: 0644]
cookbooks/prometheus/templates/default/ssl.yml.erb [new file with mode: 0644]
cookbooks/python/recipes/default.rb
cookbooks/python/resources/virtualenv.rb
cookbooks/roundup/README.md [deleted file]
cookbooks/rsyncd/metadata.rb
cookbooks/rsyncd/recipes/default.rb
cookbooks/serverinfo/recipes/default.rb
cookbooks/snmpd/attributes/default.rb
cookbooks/snmpd/recipes/default.rb
cookbooks/snmpd/templates/default/snmpd.conf.erb
cookbooks/spamassassin/metadata.rb
cookbooks/spamassassin/recipes/default.rb
cookbooks/spamassassin/templates/default/spamassassin.erb
cookbooks/squid/attributes/default.rb
cookbooks/squid/metadata.rb
cookbooks/squid/recipes/default.rb
cookbooks/squid/resources/fragment.rb
cookbooks/squid/templates/default/squid.conf.erb
cookbooks/ssl/attributes/default.rb
cookbooks/ssl/files/default/dhparam.pem [new file with mode: 0644]
cookbooks/ssl/files/default/letsencrypt.pem [deleted file]
cookbooks/ssl/recipes/default.rb
cookbooks/ssl/resources/certificate.rb
cookbooks/stateofthemap/recipes/default.rb
cookbooks/stateofthemap/templates/default/apache.erb
cookbooks/stateofthemap/templates/default/apache.jekyll.erb
cookbooks/stateofthemap/templates/default/apache.static.erb
cookbooks/stateofthemap/templates/default/backup.cron.erb
cookbooks/subversion/recipes/default.rb
cookbooks/subversion/templates/default/apache.erb
cookbooks/subversion/templates/default/backup.cron.erb
cookbooks/supybot/attributes/default.rb [new file with mode: 0644]
cookbooks/supybot/metadata.rb
cookbooks/supybot/recipes/default.rb
cookbooks/supybot/templates/default/git.conf.erb
cookbooks/supybot/templates/default/supybot.conf.erb
cookbooks/switch2osm/metadata.rb
cookbooks/switch2osm/recipes/default.rb
cookbooks/switch2osm/templates/default/apache.erb [new file with mode: 0644]
cookbooks/switch2osm/templates/default/backup.cron.erb [deleted file]
cookbooks/sysctl/attributes/default.rb [new file with mode: 0644]
cookbooks/sysctl/recipes/default.rb
cookbooks/sysctl/templates/default/chef.conf.erb [deleted file]
cookbooks/sysfs/recipes/default.rb
cookbooks/systemd/resources/path.rb
cookbooks/systemd/resources/service.rb
cookbooks/systemd/resources/timer.rb
cookbooks/systemd/resources/tmpfile.rb
cookbooks/systemd/templates/default/service.erb
cookbooks/taginfo/attributes/default.rb
cookbooks/taginfo/metadata.rb
cookbooks/taginfo/recipes/default.rb
cookbooks/tile/attributes/default.rb
cookbooks/tile/files/default/bin/expire-tiles-single
cookbooks/tile/files/default/html/favicon.ico
cookbooks/tile/metadata.rb
cookbooks/tile/recipes/default.rb
cookbooks/tile/templates/default/apache.erb
cookbooks/tile/templates/default/cleanup-tiles.cron.erb [deleted file]
cookbooks/tile/templates/default/cleanup-tiles.erb
cookbooks/tile/templates/default/debug.erb
cookbooks/tile/templates/default/expire-tiles.erb
cookbooks/tile/templates/default/export.erb
cookbooks/tile/templates/default/render-lowzoom.erb
cookbooks/tile/templates/default/renderd.conf.erb
cookbooks/tile/templates/default/replicate.erb
cookbooks/tile/templates/default/update-lowzoom.erb
cookbooks/tilecache/attributes/default.rb
cookbooks/tilecache/files/default/tilecache-curl-time.txt [new file with mode: 0644]
cookbooks/tilecache/metadata.rb
cookbooks/tilecache/recipes/default.rb
cookbooks/tilecache/templates/default/cron.erb [deleted file]
cookbooks/tilecache/templates/default/logrotate.squid.erb
cookbooks/tilecache/templates/default/nginx_generate_tilecache_qos_map.erb
cookbooks/tilecache/templates/default/nginx_tile.conf.erb
cookbooks/tilecache/templates/default/ohai.rb.erb [new file with mode: 0644]
cookbooks/tilecache/templates/default/squid.conf.erb
cookbooks/tilecache/templates/default/tilecache-curl-time-cleanup.erb [new file with mode: 0644]
cookbooks/tilecache/templates/default/tilecache-curl-time.erb [new file with mode: 0644]
cookbooks/tilelog/recipes/default.rb
cookbooks/tilelog/templates/default/tilelog.cron.erb [deleted file]
cookbooks/timescaledb/README.md [new file with mode: 0644]
cookbooks/timescaledb/attributes/default.rb [new file with mode: 0644]
cookbooks/timescaledb/metadata.rb [new file with mode: 0644]
cookbooks/timescaledb/recipes/default.rb [new file with mode: 0644]
cookbooks/tools/attributes/default.rb [new file with mode: 0644]
cookbooks/tools/recipes/default.rb
cookbooks/tools/templates/default/motd-news.erb [new file with mode: 0644]
cookbooks/trac/attributes/default.rb [new file with mode: 0644]
cookbooks/trac/files/default/htdocs/robots.txt
cookbooks/trac/metadata.rb
cookbooks/trac/recipes/default.rb
cookbooks/trac/templates/default/apache.erb
cookbooks/trac/templates/default/backup.cron.erb
cookbooks/web/attributes/default.rb
cookbooks/web/files/default/static/openlayers/OpenLayers.js [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/OpenStreetMap.js [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/404.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/blank.gif [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/cloud-popup-relative.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/drag-rectangle-off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/drag-rectangle-on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/east-mini.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/layer-switcher-maximize.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/layer-switcher-minimize.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/marker-blue.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/marker-gold.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/marker-green.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/marker.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/measuring-stick-off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/measuring-stick-on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/north-mini.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/panning-hand-off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/panning-hand-on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/slider.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/south-mini.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/west-mini.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/zoom-minus-mini.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/zoom-plus-mini.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/zoom-world-mini.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/img/zoombar.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/google.css [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/ie6-style.css [new file with mode: 0755]
cookbooks/web/files/default/static/openlayers/theme/default/img/add_point_off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/add_point_on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/blank.gif [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/close.gif [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/drag-rectangle-off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/drag-rectangle-on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/draw_line_off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/draw_line_on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/draw_point_off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/draw_point_on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/draw_polygon_off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/draw_polygon_on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/editing_tool_bar.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/move_feature_off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/move_feature_on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/navigation_history.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/overview_replacement.gif [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/pan-panel-NOALPHA.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/pan-panel.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/pan_off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/pan_on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/panning-hand-off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/panning-hand-on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/remove_point_off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/remove_point_on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/ruler.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/save_features_off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/save_features_on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/view_next_off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/view_next_on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/view_previous_off.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/view_previous_on.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/zoom-panel-NOALPHA.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/img/zoom-panel.png [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/style.css [new file with mode: 0644]
cookbooks/web/files/default/static/openlayers/theme/default/style.mobile.css [new file with mode: 0644]
cookbooks/web/metadata.rb
cookbooks/web/recipes/backend.rb
cookbooks/web/recipes/base.rb
cookbooks/web/recipes/cgimap.rb
cookbooks/web/recipes/cleanup.rb
cookbooks/web/recipes/frontend.rb
cookbooks/web/recipes/rails.rb
cookbooks/web/recipes/statistics.rb
cookbooks/web/resources/rails_port.rb
cookbooks/web/templates/default/apache.backend.erb
cookbooks/web/templates/default/apache.frontend.erb
cookbooks/web/templates/default/api-statistics.erb
cookbooks/wiki/metadata.rb
cookbooks/wiki/recipes/default.rb
cookbooks/wiki/templates/default/mw-ext-MultiMaps.inc.php.erb
cookbooks/wiki/templates/default/mw-ext-Wikibase.inc.php.erb
cookbooks/wiki/templates/default/wiki-dump.erb [deleted file]
cookbooks/wordpress/attributes/default.rb
cookbooks/wordpress/libraries/wordpress.rb
cookbooks/wordpress/metadata.rb
cookbooks/wordpress/recipes/default.rb
cookbooks/wordpress/resources/plugin.rb
cookbooks/wordpress/resources/site.rb
cookbooks/wordpress/resources/theme.rb
cookbooks/wordpress/templates/default/apache.erb
hooks/pre-commit
roles/aarnet.rb
roles/albi.rb [new file with mode: 0644]
roles/altavoz.rb
roles/angor.rb
roles/appliwave.rb [new file with mode: 0644]
roles/ar.rb [new file with mode: 0644]
roles/ascalon.rb
roles/aws.rb [deleted file]
roles/azure.rb [deleted file]
roles/backup.rb
roles/balerion.rb
roles/base.rb
roles/blix.rb
roles/boitata.rb
roles/bowser.rb
roles/bytemark.rb
roles/c3sl.rb
roles/carnet.rb
roles/catalyst.rb [deleted file]
roles/cherufe.rb
roles/chrysophylax.rb
roles/cmok.rb
roles/co.rb [new file with mode: 0644]
roles/crm.rb
roles/culebre.rb [deleted file]
roles/datahata.rb
roles/db-master.rb
roles/db-slave.rb
roles/db.rb
roles/delta.rb [deleted file]
roles/dev.rb
roles/dns.rb
roles/donate.rb
roles/dotsrc.rb [deleted file]
roles/drogon.rb
roles/dulcy.rb
roles/eddie.rb
roles/epix.rb [new file with mode: 0644]
roles/equinix.rb
roles/euserv.rb [deleted file]
roles/exonetric.rb
roles/fafnir.rb
roles/faimaison.rb [new file with mode: 0644]
roles/ffrl.rb
roles/firefishynet.rb
roles/firnen.rb [new file with mode: 0644]
roles/forum.rb
roles/foundation.rb
roles/fume.rb
roles/g5solutions.rb [deleted file]
roles/gandi.rb [new file with mode: 0644]
roles/gorynych.rb
roles/gps-tile.rb
roles/greenmini.rb [new file with mode: 0644]
roles/grifon.rb
roles/grindtooth.rb
roles/grisu.rb
roles/grnet.rb
roles/hetzner.rb
roles/hostedinnz.rb [deleted file]
roles/hp-dl360-g6.rb
roles/imagery.rb
roles/inxza.rb
roles/irc.rb
roles/ironbelly.rb
roles/iway.rb
roles/jakelong.rb [deleted file]
roles/jump.rb
roles/kalessin.rb
roles/karm.rb
roles/katie.rb [deleted file]
roles/katla.rb
roles/keizer.rb
roles/kessie.rb
roles/kibana.rb
roles/kokosnuss.rb [new file with mode: 0644]
roles/konqi.rb [deleted file]
roles/ladon.rb
roles/letsencrypt.rb
roles/logstash-forwarder.rb
roles/logstash.rb
roles/longma.rb
roles/lu.rb [new file with mode: 0644]
roles/lyonix.rb
roles/lysator.rb
roles/mail.rb
roles/meraxes.rb [new file with mode: 0644]
roles/milkywan.rb
roles/naga.rb
roles/nchc.rb
roles/neak.rb [new file with mode: 0644]
roles/necrosan.rb
roles/nepomuk.rb
roles/netalerts.rb
roles/nidhogg.rb
roles/nominatim.rb
roles/noomoahk.rb [deleted file]
roles/norbert.rb
roles/odin.rb
roles/orm.rb
roles/osqa.rb
roles/osuosl.rb
roles/otrs.rb
roles/ovh.rb
roles/paulla.rb
roles/piwik.rb
roles/pl.rb [new file with mode: 0644]
roles/planet.rb
roles/prgmr.rb [deleted file]
roles/prometheus.rb [new file with mode: 0644]
roles/proxgroup.rb [deleted file]
roles/pummelzacken.rb
roles/pyrene.rb
roles/rhaegal.rb
roles/ridgeback.rb
roles/ridley.rb
roles/rimfaxe.rb [deleted file]
roles/roundup.rb [deleted file]
roles/saphira.rb
roles/sarel.rb
roles/sarkany.rb
roles/scaleway.rb [new file with mode: 0644]
roles/scorch.rb
roles/shenron.rb
roles/shruikan.rb [new file with mode: 0644]
roles/simurgh.rb [deleted file]
roles/snap-01.rb [new file with mode: 0644]
roles/snap-02.rb [new file with mode: 0644]
roles/spike-04.rb
roles/spike-05.rb
roles/stormfly-01.rb [deleted file]
roles/stormfly-02.rb [deleted file]
roles/stormfly-03.rb [new file with mode: 0644]
roles/stormfly-04.rb [new file with mode: 0644]
roles/strato.rb [new file with mode: 0644]
roles/supybot.rb
roles/szerverem.rb
roles/tabaluga.rb
roles/taginfo.rb
roles/takhisis.rb [new file with mode: 0644]
roles/teleservice.rb
roles/teraswitch.rb
roles/tetaneutral.rb [deleted file]
roles/thorn-01.rb
roles/thorn-02.rb
roles/thorn-03.rb
roles/thorn-04.rb
roles/thorn-05.rb
roles/tiamat-00.rb
roles/tile.rb
roles/tilecache.rb
roles/toothless.rb
roles/trac.rb
roles/trogdor.rb
roles/tuatara.rb [deleted file]
roles/tuxis.rb [new file with mode: 0644]
roles/tyan-s7010.rb
roles/ucl.rb
roles/umu.rb
roles/unizar.rb [deleted file]
roles/utelecom.rb
roles/vipertooth.rb
roles/viserion.rb
roles/waima.rb [deleted file]
roles/web-backend.rb
roles/web-db.rb
roles/web-frontend.rb
roles/web.rb
roles/wiki.rb
roles/yandex.rb
roles/ysera.rb
roles/zcu.rb
test/data_bags/accounts/donate.json [new file with mode: 0644]
test/data_bags/accounts/git.json [new file with mode: 0644]
test/data_bags/accounts/gpstile.json [new file with mode: 0644]
test/data_bags/accounts/kibana.json [new file with mode: 0644]
test/data_bags/accounts/lonvia.json [new file with mode: 0644]
test/data_bags/accounts/nominatim.json [new file with mode: 0644]
test/data_bags/accounts/osmbackup.json [new file with mode: 0644]
test/data_bags/accounts/osqa.json [new file with mode: 0644]
test/data_bags/accounts/planet.json [new file with mode: 0644]
test/data_bags/accounts/rails.json [new file with mode: 0644]
test/data_bags/accounts/supybot.json [new file with mode: 0644]
test/data_bags/accounts/taginfo.json [new file with mode: 0644]
test/data_bags/accounts/tile.json [new file with mode: 0644]
test/data_bags/accounts/trac.json [new file with mode: 0644]
test/data_bags/accounts/wiki.json [new file with mode: 0644]
test/data_bags/accounts/wordpress.json [new file with mode: 0644]
test/data_bags/blog/passwords.json [new file with mode: 0644]
test/data_bags/civicrm/passwords.json [new file with mode: 0644]
test/data_bags/db/passwords.json [new file with mode: 0644]
test/data_bags/db/wal-secrets.json [new file with mode: 0644]
test/data_bags/dns/passwords.json [new file with mode: 0644]
test/data_bags/donate/passwords.json [new file with mode: 0644]
test/data_bags/exim/aliases.json [new file with mode: 0644]
test/data_bags/exim/dkim.json [new file with mode: 0644]
test/data_bags/geoipupdate/license-keys.json [new file with mode: 0644]
test/data_bags/letsencrypt/.gitkeep [new file with mode: 0644]
test/data_bags/logstash/keys.json [new file with mode: 0644]
test/data_bags/networking/keys.json [new file with mode: 0644]
test/data_bags/piwik/passwords.json [new file with mode: 0644]
test/data_bags/prometheus/passwords.json [new file with mode: 0644]
test/data_bags/prometheus/tokens.json [new file with mode: 0644]
test/data_bags/snmpd/communities.json [new file with mode: 0644]
test/data_bags/stateofthemap/passwords.json [new file with mode: 0644]
test/data_bags/supybot/passwords.json [new file with mode: 0644]
test/data_bags/supybot/users.json [new file with mode: 0644]
test/data_bags/tile/blocks.json [new file with mode: 0644]
test/data_bags/web/passwords.json [new file with mode: 0644]
test/data_bags/web/piwik.json [new file with mode: 0644]
test/data_bags/wiki/passwords.json [new file with mode: 0644]
test/integration/apache/serverspec/apache_spec.rb
test/integration/bind/serverspec/bind_spec.rb
test/integration/blog/serverspec/apache_spec.rb [moved from test/integration/apache-ssl/serverspec/apache_spec.rb with 77% similarity]
test/integration/blogs/serverspec/apache_spec.rb
test/integration/civicrm/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/clamav/serverspec/clamav_spec.rb [new file with mode: 0644]
test/integration/dhcpd/serverspec/dhcpd_spec.rb [new file with mode: 0644]
test/integration/dmca/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/dns/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/donate/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/donate/serverspec/mysql_spec.rb [new file with mode: 0644]
test/integration/elasticsearch/serverspec/elasticsearch_spec.rb [new file with mode: 0644]
test/integration/exim/serverspec/exim_spec.rb [new file with mode: 0644]
test/integration/fail2ban/serverspec/fail2ban_spec.rb [new file with mode: 0644]
test/integration/forum/serverspec/apache_spec.rb
test/integration/forum/serverspec/mysql_spec.rb
test/integration/ftp/serverspec/vsftpd_spec.rb [new file with mode: 0644]
test/integration/git-web/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/git-web/serverspec/gitweb_spec.rb [new file with mode: 0644]
test/integration/git/serverspec/git_spec.rb [new file with mode: 0644]
test/integration/gps-tile/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/gps-tile/serverspec/gpsupdate_spec.rb [new file with mode: 0644]
test/integration/hot/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/incron/serverspec/incron_spec.rb [new file with mode: 0644]
test/integration/irc/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/kibana/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/logstash-forwarder/serverspec/filebeat_spec.rb [new file with mode: 0644]
test/integration/logstash/serverspec/elasticsearch_spec.rb [new file with mode: 0644]
test/integration/logstash/serverspec/logstash_spec.rb [new file with mode: 0644]
test/integration/mail/serverspec/clamav_spec.rb [new file with mode: 0644]
test/integration/mail/serverspec/exim_spec.rb [new file with mode: 0644]
test/integration/mail/serverspec/spamassassin_spec.rb [new file with mode: 0644]
test/integration/mailman/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/mailman/serverspec/mailman_spec.rb [new file with mode: 0644]
test/integration/memcached/serverspec/memcached_spec.rb [new file with mode: 0644]
test/integration/munin-server/serverspec/apache_spec.rb
test/integration/munin/serverspec/munin_node_spec.rb
test/integration/mysql/serverspec/mysql_spec.rb
test/integration/nginx/serverspec/nginx_spec.rb [new file with mode: 0644]
test/integration/nodejs/serverspec/nodejs_spec.rb [new file with mode: 0644]
test/integration/nominatim/serverspec/nginx_spec.rb [new file with mode: 0644]
test/integration/ntp/serverspec/chronyd_spec.rb [new file with mode: 0644]
test/integration/openssh/serverspec/openssh_spec.rb [new file with mode: 0644]
test/integration/osmosis/serverspec/osmosis_spec.rb [new file with mode: 0644]
test/integration/osqa/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/otrs/serverspec/apache_spec.rb
test/integration/php-apache/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/piwik/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/planet-dump/serverspec/planetdump_spec.rb [new file with mode: 0644]
test/integration/planet-notes/serverspec/planetdump_spec.rb [new file with mode: 0644]
test/integration/planet/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/postgresql/serverspec/postgresql_spec.rb [new file with mode: 0644]
test/integration/prometheus-server/serverspec/alertmanager_spec.rb [new file with mode: 0644]
test/integration/prometheus-server/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/prometheus-server/serverspec/grafana_spec.rb [new file with mode: 0644]
test/integration/prometheus-server/serverspec/prometheus_spec.rb [new file with mode: 0644]
test/integration/prometheus-server/serverspec/promscale_spec.rb [new file with mode: 0644]
test/integration/prometheus/serverspec/prometheus_node_exporter_spec.rb [new file with mode: 0644]
test/integration/rsyncd/serverspec/rsync_spec.rb [new file with mode: 0644]
test/integration/serverinfo/gdsnd_spec.rb [new file with mode: 0644]
test/integration/serverinfo/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/snmpd/serverspec/snmpd_spec.rb [new file with mode: 0644]
test/integration/spamassassin/serverspec/spamassassin_spec.rb [new file with mode: 0644]
test/integration/squid/serverspec/squid_spec.rb [new file with mode: 0644]
test/integration/stateofhemap/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/subversion/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/subversion/serverspec/subversion_spec.rb [new file with mode: 0644]
test/integration/supybot/serverspec/supybot_spec.rb [new file with mode: 0644]
test/integration/switch2osm/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/sysfs/serverspec/sysfsutils_spec.rb [new file with mode: 0644]
test/integration/taginfo/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/tile/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/tilecache/serverspec/nginx_spec.rb [new file with mode: 0644]
test/integration/tilecache/serverspec/squid_spec.rb [new file with mode: 0644]
test/integration/trac/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/web-backend/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/web-backend/serverspec/cgimap_spec.rb [new file with mode: 0644]
test/integration/web-backend/serverspec/rails_spec.rb [new file with mode: 0644]
test/integration/web-cgimap/serverspec/cgimap_spec.rb [new file with mode: 0644]
test/integration/web-frontend/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/web-frontend/serverspec/cgimap_spec.rb [new file with mode: 0644]
test/integration/web-frontend/serverspec/memcached_spec.rb [new file with mode: 0644]
test/integration/web-frontend/serverspec/rails_spec.rb [new file with mode: 0644]
test/integration/web-rails/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/web-rails/serverspec/rails_spec.rb [new file with mode: 0644]
test/integration/wiki/serverspec/apache_spec.rb [new file with mode: 0644]
test/integration/wordpress/serverspec/apache_spec.rb [new file with mode: 0644]

diff --git a/.editorconfig b/.editorconfig
new file mode 100644 (file)
index 0000000..c0d0101
--- /dev/null
@@ -0,0 +1,11 @@
+# EditorConfig is awesome: https://EditorConfig.org
+
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+trim_trailing_whitespace = true
+insert_final_newline = true
+end_of_line = lf
+indent_size = 2
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644 (file)
index 0000000..9f77688
--- /dev/null
@@ -0,0 +1,10 @@
+version: 2
+updates:
+  - package-ecosystem: "bundler"
+    directory: "/"
+    schedule:
+      interval: "daily"
+  - package-ecosystem: "github-actions"
+    directory: "/"
+    schedule:
+      interval: "daily"
diff --git a/.github/workflows/cookstyle.yml b/.github/workflows/cookstyle.yml
new file mode 100644 (file)
index 0000000..56603f5
--- /dev/null
@@ -0,0 +1,27 @@
+name: Cookstyle
+on:
+  - push
+  - pull_request
+jobs:
+  cookstyle:
+    name: Cookstyle
+    runs-on: ubuntu-latest
+    steps:
+    - name: Check out code
+      uses: actions/checkout@v2
+    - name: Setup ruby
+      uses: actions/setup-ruby@v1.1.3
+    - name: Cache gems
+      uses: actions/cache@v2.1.4
+      with:
+        path: vendor/bundle
+        key: bundle-${{ runner.OS }}-${{ hashFiles('Gemfile.lock') }}
+        restore-keys: |
+          bundle-${{ runner.OS }}-
+    - name: Install gems
+      run: |
+        gem install bundler
+        bundle config set deployment true
+        bundle install --jobs 4 --retry 3
+    - name: Run cookstyle
+      run: bundle exec cookstyle --format fuubar
diff --git a/.github/workflows/test-kitchen.yml b/.github/workflows/test-kitchen.yml
new file mode 100644 (file)
index 0000000..297d0bb
--- /dev/null
@@ -0,0 +1,135 @@
+name: Test Kitchen
+on:
+  - push
+  - pull_request
+jobs:
+  kitchen:
+    name: Test Kitchen
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        suite:
+          - accounts
+          - apache
+          - apt
+          - backup
+          - bind
+          - blog
+          - blogs
+          - civicrm
+          - clamav
+          - db-backup
+          - db-base
+          - db-master
+          - db-slave
+          - devices
+          - dhcpd
+          - dmca
+          - dns
+          - docker
+          - donate
+          - elasticsearch
+          - exim
+          - fail2ban
+          - forum
+          - ftp
+          - geodns
+          - geoipupdate
+          - git
+          - git-server
+          - git-web
+          - gps-tile
+          - hardware
+          - hot
+          - incron
+          - irc
+          - kibana
+          - letsencrypt
+          - logstash
+          - logstash-forwarder
+          - mail
+          - mailman
+          - memcached
+          - munin
+          - munin-plugins
+          - munin-server
+          - mysql
+          - networking
+          - nginx
+          - nodejs
+          - nominatim
+          - ntp
+          - openssh
+          - osmosis
+          - osqa
+          - otrs
+          - passenger
+          - php
+          - php-apache
+          - php-fpm
+          - piwik
+          - planet
+          - planet-current
+          - planet-dump
+          - planet-notes
+          - planet-replication
+          - postgresql
+          - prometheus
+          - prometheus-server
+          - python
+          - rsyncd
+          - serverinfo
+          - snmpd
+          - spamassassin
+          - squid
+          - ssl
+          - stateofthemap
+          - subversion
+          - supybot
+          - switch2osm
+          - sysctl
+          - sysfs
+          - taginfo
+          - tile
+          - tilecache
+          - tilelog
+          - tools
+          - trac
+          - web-backend
+          - web-cgimap
+          - web-frontend
+          - web-rails
+          - wordpress
+          - wiki
+        os:
+          - ubuntu-2004
+        include:
+          - suite: trac
+            os: ubuntu-1804
+        exclude:
+          - suite: trac
+            os: ubuntu-2004
+      fail-fast: false
+    steps:
+    - name: Check out code
+      uses: actions/checkout@v2
+    - name: Setup ruby
+      uses: actions/setup-ruby@v1.1.3
+    - name: Cache gems
+      uses: actions/cache@v2.1.4
+      with:
+        path: vendor/bundle
+        key: bundle-${{ runner.OS }}-${{ hashFiles('Gemfile.lock') }}
+        restore-keys: |
+          bundle-${{ runner.OS }}-
+    - name: Disable apparmor for mysqld
+      run: |
+        sudo apt-get install apparmor-utils
+        sudo aa-disable /usr/sbin/mysqld
+    - name: Install gems
+      run: |
+        gem install bundler
+        bundle config set deployment true
+        bundle install --jobs 4 --retry 3
+    - name: Run kitchen test ${{ matrix.suite }}-${{ matrix.os }}
+      run: bundle exec kitchen test ${{ matrix.suite }}-${{ matrix.os }}
index 82d1b5caa3af3d2a880e01e105742b24fff0a22a..b31363aa4261a906fae966c5edcd8217fea66a57 100644 (file)
@@ -1,2 +1,3 @@
+.DS_Store
 .kitchen/
 .kitchen.local.yml
diff --git a/.kitchen.provision.rb b/.kitchen.provision.rb
deleted file mode 100644 (file)
index 8398bd5..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-Vagrant.configure(2) do |config|
-  config.vm.provision "shell", :inline => <<-SHELL
-    apt-get update -y
-  SHELL
-end
index 1b49363e6b13698d9dc3108e01e4596527ccb2b2..58a63e3b9871a41e73e3890723c812dd084a1e1a 100644 (file)
@@ -1,16 +1,37 @@
 ---
 driver:
-  name: vagrant
-  provision: true
-  vagrantfiles:
-    - .kitchen.provision.rb
+  name: dokken
+  chef_version: 16
+  env:
+    - container=dokken
+
+transport:
+  name: dokken
 
 provisioner:
-  name: chef_zero
+  name: dokken
+  chef_license: accept
   data_bags_path: test/data_bags
 
+verifier:
+  root_path: /opt/verifier
+  sudo: false
+
 platforms:
-  - name: ubuntu-16.04
+  - name: ubuntu-18.04
+    driver:
+      image: dokken/ubuntu-18.04
+      privileged: true
+      pid_one_command: /bin/systemd
+      intermediate_instructions:
+        - RUN /usr/bin/apt-get update -y
+  - name: ubuntu-20.04
+    driver:
+      image: dokken/ubuntu-20.04
+      privileged: true
+      pid_one_command: /bin/systemd
+      intermediate_instructions:
+        - RUN /usr/bin/apt-get update -y
 
 suites:
   - name: accounts
@@ -19,35 +40,165 @@ suites:
   - name: apache
     run_list:
       - recipe[apache::default]
-  - name: apache-ssl
-    run_list:
-      - recipe[apache::ssl]
   - name: apt
     run_list:
       - recipe[apt::default]
+  - name: backup
+    run_list:
+      - recipe[backup::default]
   - name: bind
     run_list:
       - recipe[bind::default]
+    attributes:
+      bind:
+        clients: none
+  - name: blog
+    run_list:
+      - recipe[blog::default]
   - name: blogs
     run_list:
-      - recipe[accounts::default]
       - recipe[blogs::default]
+  - name: civicrm
+    run_list:
+      - recipe[civicrm::default]
+  - name: clamav
+    run_list:
+      - recipe[clamav::default]
+  - name: db-backup
+    run_list:
+      - recipe[db::backup]
+  - name: db-base
+    run_list:
+      - recipe[db::base]
+  - name: db-master
+    run_list:
+      - recipe[db::master]
+  - name: db-slave
+    run_list:
+      - recipe[db::slave]
+  - name: devices
+    run_list:
+      - recipe[devices::default]
+  - name: dhcpd
+    run_list:
+      - recipe[dhcpd::default]
+    attributes:
+      dhcpd:
+        first_address: 172.18.100.1
+        last_address: 172.18.100.254
+      networking:
+        interfaces:
+          test:
+            interface: eth0
+            role: internal
+            address: 172.18.0.2
+            prefix: 16
+            gateway: 172.18.0.1
+        roles:
+          external:
+            zone: test
+  - name: dmca
+    run_list:
+      - recipe[dmca::default]
+  - name: dns
+    run_list:
+      - recipe[dns::default]
+  - name: docker
+    run_list:
+      - recipe[docker::default]
+  - name: donate
+    run_list:
+      - recipe[donate::default]
+  - name: elasticsearch
+    run_list:
+      - recipe[elasticsearch::default]
+  - name: exim
+    run_list:
+      - recipe[exim::default]
+  - name: fail2ban
+    run_list:
+      - recipe[fail2ban::default]
   - name: forum
     run_list:
-      - recipe[accounts::default]
-      - role[forum]
+      - recipe[forum::default]
+  - name: ftp
+    run_list:
+      - recipe[ftp::default]
+  - name: geodns
+    run_list:
+      - recipe[geodns::default]
+    attributes:
+      networking:
+        interfaces:
+          test:
+            role: external
+            address: 172.18.0.2
+  - name: geoipupdate
+    run_list:
+      - recipe[geoipupdate::default]
+  - name: git
+    run_list:
+      - recipe[git::default]
+  - name: git-server
+    run_list:
+      - recipe[git::server]
+  - name: git-web
+    run_list:
+      - recipe[git::web]
+  - name: gps-tile
+    run_list:
+      - recipe[gps-tile::default]
+  - name: hardware
+    run_list:
+      - recipe[hardware::default]
+  - name: hot
+    run_list:
+      - recipe[hot::default]
+  - name: incron
+    run_list:
+      - recipe[incron::default]
+  - name: irc
+    run_list:
+      - recipe[irc::default]
+  - name: kibana
+    run_list:
+      - recipe[kibana::default]
   - name: letsencrypt
     run_list:
-      - recipe[accounts::default]
-      - recipe[apt::default]
-      - role[letsencrypt]
+      - recipe[letsencrypt::default]
     attributes:
       apt:
         sources:
           - openstreetmap
+  - name: logstash
+    run_list:
+      - recipe[logstash::default]
+  - name: logstash-forwarder
+    run_list:
+      - recipe[logstash::forwarder]
+    attributes:
+      logstash:
+        forwarder:
+          filebeat.prospectors:
+            - input_type: log
+              paths:
+                - /var/log/apache2/access.log
+              type: apache
+  - name: mail
+    run_list:
+      - role[mail]
+  - name: mailman
+    run_list:
+      - recipe[mailman::default]
+  - name: memcached
+    run_list:
+      - recipe[memcached::default]
   - name: munin
     run_list:
       - recipe[munin::default]
+  - name: munin-plugins
+    run_list:
+      - recipe[munin::plugins]
   - name: munin-server
     run_list:
       - recipe[munin::server]
@@ -57,14 +208,167 @@ suites:
   - name: networking
     run_list:
       - recipe[networking::default]
+  - name: nginx
+    run_list:
+      - recipe[nginx::default]
+  - name: nodejs
+    run_list:
+      - recipe[nodejs::default]
+  - name: nominatim
+    run_list:
+      - recipe[nominatim::default]
+  - name: ntp
+    run_list:
+      - recipe[ntp::default]
+  - name: openssh
+    run_list:
+      - recipe[openssh::default]
+  - name: osmosis
+    run_list:
+      - recipe[osmosis::default]
+  - name: osqa
+    run_list:
+      - recipe[osqa::default]
   - name: otrs
     run_list:
-      - recipe[accounts::default]
-      - recipe[chef::default]
-      - role[otrs]
+      - recipe[otrs::default]
+  - name: passenger
+    run_list:
+      - recipe[passenger::default]
+  - name: php
+    run_list:
+      - recipe[php::default]
+  - name: php-apache
+    run_list:
+      - recipe[php::apache]
+  - name: php-fpm
+    run_list:
+      - recipe[php::fpm]
+  - name: piwik
+    run_list:
+      - recipe[piwik::default]
+  - name: planet
+    run_list:
+      - recipe[planet::default]
+  - name: planet-current
+    run_list:
+      - recipe[planet::current]
+  - name: planet-dump
+    run_list:
+      - recipe[planet::dump]
+  - name: planet-notes
+    run_list:
+      - recipe[planet::notes]
+    attributes:
+      web:
+        readonly_database_host: readonly
+  - name: planet-replication
+    run_list:
+      - recipe[planet::replication]
+    attributes:
+      web:
+        readonly_database_host: readonly
+  - name: postgresql
+    run_list:
+      - recipe[postgresql::default]
+    attributes:
+      postgresql:
+        versions:
+          - 10
+  - name: prometheus
+    run_list:
+      - recipe[prometheus::default]
+    attributes:
+      networking:
+        interfaces:
+          test:
+            interface: eth0
+            role: internal
+            address: 172.18.0.2
+            prefix: 16
+            gateway: 172.18.0.1
+  - name: prometheus-server
+    run_list:
+      - recipe[prometheus::server]
   - name: python
     run_list:
       - recipe[python::default]
+  - name: rsyncd
+    run_list:
+      - recipe[rsyncd::default]
+  - name: serverinfo
+    run_list:
+      - recipe[serverinfo::default]
+  - name: snmpd
+    run_list:
+      - recipe[snmpd::default]
+  - name: spamassassin
+    run_list:
+      - recipe[spamassassin::default]
+  - name: squid
+    run_list:
+      - recipe[squid::default]
+  - name: ssl
+    run_list:
+      - recipe[ssl::default]
+  - name: stateofthemap
+    run_list:
+      - recipe[stateofthemap::default]
+  - name: subversion
+    run_list:
+      - recipe[subversion::default]
+  - name: supybot
+    run_list:
+      - recipe[supybot::default]
+  - name: switch2osm
+    run_list:
+      - recipe[switch2osm::default]
+  - name: sysctl
+    run_list:
+      - recipe[sysctl::default]
+  - name: sysfs
+    run_list:
+      - recipe[sysfs::default]
+  - name: taginfo
+    run_list:
+      - recipe[taginfo::default]
+    attributes:
+      taginfo:
+        sites:
+          - name: taginfo.example.com
+  - name: tile
+    run_list:
+      - recipe[tile::default]
+  - name: tilecache
+    run_list:
+      - recipe[tilecache::default]
+  - name: tilelog
+    run_list:
+      - recipe[tilelog::default]
+  - name: timescaledb
+    run_list:
+      - recipe[timescaledb::default]
   - name: tools
     run_list:
       - recipe[tools::default]
+  - name: trac
+    run_list:
+      - recipe[trac::default]
+  - name: web-backend
+    run_list:
+      - recipe[web::backend]
+  - name: web-cgimap
+    run_list:
+      - recipe[web::cgimap]
+  - name: web-frontend
+    run_list:
+      - recipe[web::frontend]
+  - name: web-rails
+    run_list:
+      - recipe[web::rails]
+  - name: wiki
+    run_list:
+      - recipe[wiki::default]
+  - name: wordpress
+    run_list:
+      - recipe[wordpress::default]
index 90f166d5b9fab3b4f4b2d6ad5fc35d92eea916da..15718e51933286e21d1edb4d70fac5f8d649b42f 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -1,3 +1,3 @@
-Grant Slater <openstreetmap@firefishy.com> <git@firefishy.com>
+Grant Slater <openstreetmap@firefishy.com> <git@firefishy.com> <grant.slater@wearefriday.com> <github@firefishy.com>
 Guillaume Rischard <git@stereo.lu> <github@stereo.lu>
 Jochen Topf <jochen@topf.org> <jochen@remote.org>
index 5db1a31045524667dabbea1a6aaf55863ffa3ed4..80bd36dad256c088960a696f3b42a198146448c8 100644 (file)
@@ -1,17 +1,23 @@
 inherit_from: .rubocop_todo.yml
 
 AllCops:
-  TargetRubyVersion: 2.3
+  TargetRubyVersion: 2.7
+
+ChefModernize/IncludingAptDefaultRecipe:
+  Enabled: false
 
 Layout/ExtraSpacing:
   AllowForAlignment: true
 
-Layout/IndentHeredoc:
-  EnforcedStyle: squiggly
+Layout/HeredocIndentation:
+  Enabled: true
 
-Naming/UncommunicativeMethodParamName:
+Naming/MethodParameterName:
   Enabled: false
 
+Style/CommandLiteral:
+  EnforcedStyle: percent_x
+
 Style/HashSyntax:
   EnforcedStyle: hash_rockets
 
index 945610536933264131e009da5aee1778d7d59f8d..bdb397acf8f7df5de238b01ad83ab44b41d4f91c 100644 (file)
@@ -1,38 +1,19 @@
 # This configuration was generated by
 # `rubocop --auto-gen-config`
-# on 2019-09-09 18:59:09 +0100 using RuboCop version 0.72.0.
+# on 2020-07-30 08:39:06 UTC using RuboCop version 0.88.0.
 # The point is for the user to remove these configuration records
 # one by one as the offenses are removed from the code base.
 # Note that changes in the inspected code, or installation of new
 # versions of RuboCop, may require this file to be generated again.
 
-# Offense count: 14
-ChefCorrectness/NodeNormal:
-  Exclude:
-    - '**/metadata.rb'
-    - 'cookbooks/dev/recipes/default.rb'
-    - 'cookbooks/mediawiki/resources/site.rb'
-    - 'cookbooks/networking/recipes/default.rb'
-    - 'cookbooks/openvpn/recipes/default.rb'
-    - 'cookbooks/web/recipes/backend.rb'
-    - 'cookbooks/wordpress/resources/site.rb'
-
-# Offense count: 12
-ChefCorrectness/NodeNormalUnless:
-  Exclude:
-    - '**/metadata.rb'
-    - 'cookbooks/mailman/recipes/default.rb'
-    - 'cookbooks/mediawiki/resources/site.rb'
-    - 'cookbooks/wordpress/resources/site.rb'
-
-# Offense count: 947
+# Offense count: 1038
 # Cop supports --auto-correct.
 # Configuration parameters: .
 # SupportedStyles: strings, symbols
 ChefStyle/AttributeKeys:
   EnforcedStyle: symbols
 
-# Offense count: 466
-# Cop supports --auto-correct.
-ChefStyle/FileMode:
-  Enabled: false
+# Offense count: 3
+# Configuration parameters: CountBlocks.
+Metrics/BlockNesting:
+  Max: 4
index 7bf4b6a8aeff6ff21de600580d06d0047d6a34f0..860487ca19cedeaf219ae3caca5e14df61c44f18 100644 (file)
@@ -1 +1 @@
-2.4.6
+2.7.1
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644 (file)
index 87e77d6..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-sudo: false
-language: ruby
-cache: bundler
-script:
-  - bundle exec cookstyle -f fuubar
index 01e194f4a765660daf4294d5cbd74f04116ca9d2..620c6a2bad8a79c385dd2b5030b1fe22744a09ff 100644 (file)
@@ -1,15 +1,24 @@
-FROM ruby:2.6
+# Basic Dockerfile to run cookstyle linting
+# run: docker build -t chef-test .
+FROM ruby:2.7-alpine as build
 
+# Add Gem build requirements
+RUN apk add --no-cache build-base
+
+# Create app directory
 WORKDIR /app
 
-RUN apt-get update \
-       && apt-get install -y --no-install-recommends libssl-dev
+# Add Gemfile and Gemfile.lock
+ADD Gemfile* ./
 
-ADD Gemfile* /app/
-RUN gem install bundler --no-document \
+# Install Gems
+RUN gem install bundler \
     && bundle config build.nokogiri --use-system-libraries \
-    && bundle install --jobs $(nproc) --retry 5
+    && bundle config --global jobs $(nproc) \
+    && bundle install
 
-ADD . /app/
+# Add repo
+ADD . .
 
+# Run linting
 RUN bundle exec cookstyle -f fuubar
diff --git a/Gemfile b/Gemfile
index ddf1c6b1cab9ab4372204993ddcb4570689bc5e1..f04be603c0a9310adf845817dea9cb9fe682be26 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,6 @@
 source "https://rubygems.org"
 
 gem "cookstyle"
-gem "kitchen-vagrant"
+gem "kitchen-dokken"
 gem "serverspec"
 gem "test-kitchen"
index 973d415ee42189bef6e6cdf2afe5839867d08e80..65ffe696d643867790fa275fa9fe9dad28399e1a 100644 (file)
 GEM
   remote: https://rubygems.org/
   specs:
-    ast (2.4.0)
-    bcrypt_pbkdf (1.0.1)
-    builder (3.2.3)
-    cookstyle (5.9.3)
-      rubocop (= 0.72.0)
-    diff-lcs (1.3)
+    ast (2.4.2)
+    bcrypt_pbkdf (1.1.0)
+    builder (3.2.4)
+    chef-utils (16.10.17)
+    cookstyle (7.9.0)
+      rubocop (= 1.11.0)
+    diff-lcs (1.4.4)
+    docker-api (2.0.0)
+      excon (>= 0.47.0)
+      multi_json
     ed25519 (1.2.4)
-    equatable (0.6.1)
-    erubis (2.7.0)
-    ffi (1.11.1)
-    gssapi (1.3.0)
+    erubi (1.10.0)
+    excon (0.79.0)
+    ffi (1.14.2)
+    gssapi (1.3.1)
       ffi (>= 1.0.1)
     gyoku (1.3.1)
       builder (>= 2.1.2)
     httpclient (2.8.3)
-    jaro_winkler (1.5.3)
-    kitchen-vagrant (1.6.0)
-      test-kitchen (>= 1.4, < 3)
-    license-acceptance (1.0.13)
+    kitchen-dokken (2.12.1)
+      docker-api (>= 1.33, < 3)
+      lockfile (~> 2.1)
+      test-kitchen (>= 1.15, < 3)
+    license-acceptance (2.1.13)
       pastel (~> 0.7)
-      tomlrb (~> 1.2)
-      tty-box (~> 0.3)
-      tty-prompt (~> 0.18)
+      tomlrb (>= 1.2, < 3.0)
+      tty-box (~> 0.6)
+      tty-prompt (~> 0.20)
     little-plugger (1.1.4)
-    logging (2.2.2)
+    lockfile (2.1.3)
+    logging (2.3.0)
       little-plugger (~> 1.1)
-      multi_json (~> 1.10)
-    mixlib-install (3.11.21)
+      multi_json (~> 1.14)
+    mixlib-install (3.12.7)
       mixlib-shellout
       mixlib-versioning
       thor
-    mixlib-shellout (3.0.7)
-    mixlib-versioning (1.2.7)
-    multi_json (1.14.1)
-    necromancer (0.5.0)
-    net-scp (2.0.0)
-      net-ssh (>= 2.6.5, < 6.0.0)
-    net-ssh (5.2.0)
+    mixlib-shellout (3.2.5)
+      chef-utils
+    mixlib-versioning (1.2.12)
+    multi_json (1.15.0)
+    net-scp (3.0.0)
+      net-ssh (>= 2.6.5, < 7.0.0)
+    net-ssh (6.1.0)
     net-ssh-gateway (2.0.0)
       net-ssh (>= 4.0.0)
     net-telnet (0.1.1)
     nori (2.6.0)
-    parallel (1.18.0)
-    parser (2.6.5.0)
-      ast (~> 2.4.0)
-    pastel (0.7.3)
-      equatable (~> 0.6)
+    parallel (1.20.1)
+    parser (3.0.0.0)
+      ast (~> 2.4.1)
+    pastel (0.8.0)
       tty-color (~> 0.5)
     rainbow (3.0.0)
+    regexp_parser (2.1.1)
+    rexml (3.2.4)
     rspec (3.9.0)
       rspec-core (~> 3.9.0)
       rspec-expectations (~> 3.9.0)
       rspec-mocks (~> 3.9.0)
-    rspec-core (3.9.0)
-      rspec-support (~> 3.9.0)
-    rspec-expectations (3.9.0)
+    rspec-core (3.9.2)
+      rspec-support (~> 3.9.3)
+    rspec-expectations (3.9.2)
       diff-lcs (>= 1.2.0, < 2.0)
       rspec-support (~> 3.9.0)
     rspec-its (1.3.0)
       rspec-core (>= 3.0.0)
       rspec-expectations (>= 3.0.0)
-    rspec-mocks (3.9.0)
+    rspec-mocks (3.9.1)
       diff-lcs (>= 1.2.0, < 2.0)
       rspec-support (~> 3.9.0)
-    rspec-support (3.9.0)
-    rubocop (0.72.0)
-      jaro_winkler (~> 1.5.1)
+    rspec-support (3.9.3)
+    rubocop (1.11.0)
       parallel (~> 1.10)
-      parser (>= 2.6)
+      parser (>= 3.0.0.0)
       rainbow (>= 2.2.2, < 4.0)
+      regexp_parser (>= 1.8, < 3.0)
+      rexml
+      rubocop-ast (>= 1.2.0, < 2.0)
       ruby-progressbar (~> 1.7)
-      unicode-display_width (>= 1.4.0, < 1.7)
-    ruby-progressbar (1.10.1)
-    rubyntlm (0.6.2)
-    rubyzip (1.3.0)
+      unicode-display_width (>= 1.4.0, < 3.0)
+    rubocop-ast (1.4.1)
+      parser (>= 2.7.1.5)
+    ruby-progressbar (1.11.0)
+    rubyntlm (0.6.3)
+    rubyzip (2.3.0)
     serverspec (2.41.5)
       multi_json
       rspec (~> 3.0)
       rspec-its
       specinfra (~> 2.72)
     sfl (2.3)
-    specinfra (2.82.3)
+    specinfra (2.82.19)
       net-scp
       net-ssh (>= 2.7)
       net-telnet (= 0.1.1)
       sfl
-    strings (0.1.6)
-      strings-ansi (~> 0.1)
+    strings (0.2.0)
+      strings-ansi (~> 0.2)
       unicode-display_width (~> 1.5)
       unicode_utils (~> 1.4)
-    strings-ansi (0.1.0)
-    test-kitchen (2.3.3)
+    strings-ansi (0.2.0)
+    test-kitchen (2.11.1)
       bcrypt_pbkdf (~> 1.0)
+      chef-utils (>= 16.4.35)
       ed25519 (~> 1.2)
-      license-acceptance (~> 1.0, >= 1.0.11)
+      license-acceptance (>= 1.0.11, < 3.0)
       mixlib-install (~> 3.6)
       mixlib-shellout (>= 1.2, < 4.0)
-      net-scp (>= 1.1, < 3.0)
-      net-ssh (>= 2.9, < 6.0)
+      net-scp (>= 1.1, < 4.0)
+      net-ssh (>= 2.9, < 7.0)
       net-ssh-gateway (>= 1.2, < 3.0)
-      thor (~> 0.19)
+      thor (>= 0.19, < 2.0)
       winrm (~> 2.0)
       winrm-elevated (~> 1.0)
       winrm-fs (~> 1.1)
-    thor (0.20.3)
-    tomlrb (1.2.8)
-    tty-box (0.5.0)
-      pastel (~> 0.7.2)
-      strings (~> 0.1.6)
+    thor (1.1.0)
+    tomlrb (2.0.1)
+    tty-box (0.7.0)
+      pastel (~> 0.8)
+      strings (~> 0.2.0)
       tty-cursor (~> 0.7)
-    tty-color (0.5.0)
-    tty-cursor (0.7.0)
-    tty-prompt (0.19.0)
-      necromancer (~> 0.5.0)
-      pastel (~> 0.7.0)
-      tty-reader (~> 0.6.0)
-    tty-reader (0.6.0)
+    tty-color (0.6.0)
+    tty-cursor (0.7.1)
+    tty-prompt (0.23.0)
+      pastel (~> 0.8)
+      tty-reader (~> 0.8)
+    tty-reader (0.9.0)
       tty-cursor (~> 0.7)
-      tty-screen (~> 0.7)
-      wisper (~> 2.0.0)
-    tty-screen (0.7.0)
-    unicode-display_width (1.6.0)
+      tty-screen (~> 0.8)
+      wisper (~> 2.0)
+    tty-screen (0.8.1)
+    unicode-display_width (1.7.0)
     unicode_utils (1.4.0)
-    winrm (2.3.2)
+    winrm (2.3.6)
       builder (>= 2.1.2)
-      erubis (~> 2.7)
+      erubi (~> 1.8)
       gssapi (~> 1.2)
       gyoku (~> 1.0)
       httpclient (~> 2.2, >= 2.2.0.2)
       logging (>= 1.6.1, < 3.0)
       nori (~> 2.0)
-      rubyntlm (~> 0.6.0, >= 0.6.1)
-    winrm-elevated (1.1.1)
+      rubyntlm (~> 0.6.0, >= 0.6.3)
+    winrm-elevated (1.2.3)
+      erubi (~> 1.8)
       winrm (~> 2.0)
       winrm-fs (~> 1.0)
-    winrm-fs (1.3.2)
-      erubis (~> 2.7)
+    winrm-fs (1.3.5)
+      erubi (~> 1.8)
       logging (>= 1.6.1, < 3.0)
-      rubyzip (~> 1.1)
+      rubyzip (~> 2.0)
       winrm (~> 2.0)
     wisper (2.0.1)
 
@@ -148,9 +160,9 @@ PLATFORMS
 
 DEPENDENCIES
   cookstyle
-  kitchen-vagrant
+  kitchen-dokken
   serverspec
   test-kitchen
 
 BUNDLED WITH
-   1.17.2
+   2.1.4
index 8707c7b461c18a3d46329c097cf8d7a692fd4f26..65b41d6090b638a502aecc20ad0de8f3748b9fbb 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
 # OpenStreetMap chef cookbooks
 
-[![Build Status](https://travis-ci.org/openstreetmap/chef.svg?branch=master)](https://travis-ci.org/openstreetmap/chef)
+[![Cookstyle](https://github.com/openstreetmap/chef/workflows/Cookstyle/badge.svg?branch=master&event=push)](https://github.com/openstreetmap/chef/actions?query=workflow%3ACookstyle%20branch%3Amaster%20event%3Apush)
+[![Test Kitchen](https://github.com/openstreetmap/chef/workflows/Test%20Kitchen/badge.svg?branch=master&event=push)](https://github.com/openstreetmap/chef/actions?query=workflow%3A%22Test+Kitchen%22%20branch%3Amaster%20event%3Apush)
 
 This repository manages the configuration of all the servers run by the
 OpenStreetMap Foundation's Operations Working Group. We use
index 8535ee403c98bb4f8d9787095d24b88d848e63a1..e529fe2fd857b4367e3fd18e7155123d21185b82 100644 (file)
@@ -4,3 +4,4 @@ default[:accounts][:manage_home] = true
 
 default[:accounts][:groups] = {}
 default[:accounts][:users] = {}
+default[:accounts][:administrators] = []
diff --git a/cookbooks/accounts/files/default/dmlu/.ssh/authorized_keys b/cookbooks/accounts/files/default/dmlu/.ssh/authorized_keys
new file mode 100644 (file)
index 0000000..2170df5
--- /dev/null
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAqX90M2sP8AYuO7pdH8yHwu6T2RtuLFG7vzgVTiDSaEq8XvgRdaRRIECXbotwDONaOUgjlFHLo7bKc6aj1sWq21rP6FO+nL0TrzpirdspmIeCDDzkGzCRJSIIOLOzVCY8E8+JLqosrpIzScnLmDFopVpvhzBDIVF9LzYaKZc8s+kiB74Q28qKFKAzBi4mfxxkSUXSIQ3UA/CchRUef6UtSJjl04b4vnnnCG+DVO4HzCurwZq/47VIe1xwAIFavTuHniBd/iaoc2tGtclD9Je5T1ja5NaWoh3pf8hPxNpTZmGc3fex3xkHkF1x5FMu2sscgB3R0fdRaNZ9vPqu4WyY2Q== dmlu
diff --git a/cookbooks/accounts/files/default/grant/.gitconfig b/cookbooks/accounts/files/default/grant/.gitconfig
new file mode 100644 (file)
index 0000000..4e9b210
--- /dev/null
@@ -0,0 +1,9 @@
+[user]
+       email = git@firefishy.com
+       name = Grant Slater
+[push]
+       default = simple
+[core]
+       editor = vim
+[diff]
+       algorithm = histogram
index 7eb760f3cc7c8c2990903d81356e39e922f5b4a5..b395aeca615c44f3bb46546c2610e27f076fb031 100644 (file)
@@ -19,7 +19,7 @@
 
 package "zsh"
 
-administrators = []
+administrators = node[:accounts][:administrators].to_a
 
 search(:accounts, "*:*").each do |account|
   name = account["id"]
@@ -39,9 +39,15 @@ search(:accounts, "*:*").each do |account|
       user_shell = details[:shell] || account["shell"] || node[:accounts][:shell]
     end
 
+    available_users = if node[:etc]
+                        node[:etc][:passwd].keys
+                      else
+                        []
+                      end
+
     group name.to_s do
       gid account["uid"].to_i
-      members group_members & node[:etc][:passwd].keys
+      members group_members & available_users
     end
 
     user name.to_s do
@@ -58,18 +64,16 @@ search(:accounts, "*:*").each do |account|
       source name.to_s
       owner name.to_s
       group name.to_s
-      mode 0o755
+      mode "755"
       files_owner name.to_s
       files_group name.to_s
-      files_mode 0o644
+      files_mode "644"
       only_if do
-        begin
-          cookbook = run_context.cookbook_collection[cookbook_name]
-          files = cookbook.relative_filenames_in_preferred_directory(node, :files, name.to_s)
-          !files.empty?
-        rescue Chef::Exceptions::FileNotFound
-          false
-        end
+        cookbook = run_context.cookbook_collection[cookbook_name]
+        files = cookbook.relative_filenames_in_preferred_directory(node, :files, name.to_s)
+        !files.empty?
+      rescue Chef::Exceptions::FileNotFound
+        false
       end
     end
 
index cff5e5b839c1b5fb0af59eed4b16e1d32b2feb73..080ca4e3ac23c0ba62be5bc14afc538f74cabc8a 100644 (file)
@@ -1,4 +1,4 @@
-default[:apache][:mpm] = "worker"
+default[:apache][:mpm] = "event"
 
 default[:apache][:timeout] = 300
 
index 06b231a1c3c2e01c896ac84a032c198b46cf9c31..f6176ee8b8183d8a34767b6fa9d99bd38e6e56c0 100644 (file)
@@ -7,4 +7,5 @@ description       "Installs and configures apache"
 version           "1.0.0"
 supports          "ubuntu"
 depends           "munin"
+depends           "prometheus"
 depends           "ssl"
index ffa03c34cbfbdae28b2c7649ab6da7281f3bd4b1..d443f1e409ce5eff9c76c861ca67f2bddb176583 100644 (file)
@@ -17,6 +17,8 @@
 # limitations under the License.
 #
 
+include_recipe "munin"
+include_recipe "prometheus"
 include_recipe "ssl"
 
 package %w[
@@ -49,11 +51,13 @@ template "/etc/apache2/ports.conf" do
   source "ports.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 service "apache2" do
   action [:enable, :start]
+  retries 2
+  retry_delay 10
   supports :status => true, :restart => true, :reload => true
 end
 
@@ -91,3 +95,9 @@ end
 munin_plugin "apache_accesses"
 munin_plugin "apache_processes"
 munin_plugin "apache_volume"
+
+prometheus_exporter "apache" do
+  port 9117
+  listen_switch "telemetry.address"
+  options "--scrape_uri=http://localhost/server-status?auto"
+end
index 0ac19b0c795f9b64283754a900c4f74cb36a9d64..12daf87ab48ef39d5bf0e1c84b09da69a07c0f9f 100644 (file)
@@ -19,9 +19,9 @@
 
 default_action [:create, :enable]
 
-property :conf, :kind_of => String, :name_attribute => true
+property :conf, :kind_of => String, :name_property => true
 property :cookbook, :kind_of => String
-property :template, :kind_of => String, :required => true
+property :template, :kind_of => String, :required => [:create]
 property :variables, :kind_of => Hash, :default => {}
 property :reload_apache, :kind_of => [TrueClass, FalseClass], :default => true
 
@@ -48,7 +48,7 @@ action_class do
       source new_resource.template
       owner "root"
       group "root"
-      mode 0o644
+      mode "644"
       variables new_resource.variables
     end
   end
index 0ac0f8f01471cd161811c8a537155d6f774b7535..6658d52a66320e95f8fbb6045b1c0b9ec515a57d 100644 (file)
@@ -19,7 +19,7 @@
 
 default_action [:install, :enable]
 
-property :module, :kind_of => String, :name_attribute => true
+property :module, :kind_of => String, :name_property => true
 property :package, :kind_of => String
 property :conf, :kind_of => String
 property :variables, :kind_of => Hash, :default => {}
@@ -33,7 +33,7 @@ action :install do
       source new_resource.conf
       owner "root"
       group "root"
-      mode 0o644
+      mode "644"
       variables new_resource.variables
     end
   end
index 5b52304251b8dfae2609155b340c1b6b85b6f70b..e039e3ac529e93a67a88d04676678205573fd0b8 100644 (file)
 
 default_action [:create, :enable]
 
-property :site, :kind_of => String, :name_attribute => true
+property :site, :kind_of => String, :name_property => true
 property :directory, :kind_of => String
 property :cookbook, :kind_of => String
-property :template, :kind_of => String, :required => true
+property :template, :kind_of => String, :required => [:create]
 property :variables, :kind_of => Hash, :default => {}
 property :reload_apache, :kind_of => [TrueClass, FalseClass], :default => true
 
@@ -32,7 +32,7 @@ action :create do
     source new_resource.template
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables new_resource.variables.merge(:name => new_resource.site, :directory => site_directory)
   end
 end
index 81c8f6e9ff60eb3977e909e50567f089b5feb7d9..62533efae0512bee01b91b50e0f8e432591ab6d6 100644 (file)
@@ -50,6 +50,9 @@ MaxConnectionsPerChild <%= node[:apache][:event][:max_connections_per_child] %>
 <% if node[:apache][:event][:async_request_worker_factor] -%>
 AsyncRequestWorkerFactor <%= node[:apache][:event][:async_request_worker_factor] %>
 <% end -%>
+<% if node[:apache][:event][:listen_cores_buckets_ratio] -%>
+ListenCoresBucketsRatio <%= node[:apache][:event][:listen_cores_buckets_ratio] %>
+<% end -%>
 <% end -%>
 
 # Default to UTF-8
index 80735c9cb51d3d0a53e6b18a878301f635f87b52..ccfef6048761d3394ea1ea8f3a4e3010b9a59281 100644 (file)
@@ -13,4 +13,8 @@ SSLStaplingFakeTryLater off
 SSLStaplingCache shmcb:${APACHE_RUN_DIR}/ssl_ocspcache(512000)
 
 Header always set Strict-Transport-Security "<%= node[:ssl][:strict_transport_security] %>" "expr=%{HTTPS} == 'on'"
-Header always set Expect-CT "max-age=0, report-uri=\"https://openstreetmap.report-uri.com/r/d/ct/reportOnly\"" "expr=%{HTTPS} == 'on'
+<% if node[:ssl][:ct_report_uri] -%>
+Header always set Expect-CT "max-age=0, report-uri=\"<%= node[:ssl][:ct_report_uri] %>\"" "expr=%{HTTPS} == 'on'"
+<% else -%>
+Header always set Expect-CT "max-age=0" "expr=%{HTTPS} == 'on'"
+<% end -%>
index f75ed9e34abe5f4a77f1591ceea00011136f4b61..a949a1c0251300c0cac336057158cb5fffb76814 100644 (file)
@@ -1,4 +1,3 @@
-default_unless[:apt][:sources] = []
-
+default[:apt][:sources] = [ "openstreetmap" ]
 default[:apt][:unattended_upgrades][:enable] = true
 default[:apt][:unattended_upgrades][:remove_unused_dependencies] = true
index 9aa2f7a827760dc54dc5d70c5275c9d42479b496..6ab6afb7ecaf793a2a64777e30ef812f71608e31 100644 (file)
@@ -32,7 +32,7 @@ template "/etc/apt/preferences.d/99-chef" do
   source "preferences.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 apt_update "/etc/apt/sources.list" do
@@ -49,7 +49,7 @@ template "/etc/apt/sources.list" do
   source "sources.list.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   variables :archive_host => archive_host, :codename => node[:lsb][:codename]
   notifies :update, "apt_update[/etc/apt/sources.list]", :immediately
 end
@@ -73,6 +73,16 @@ apt_repository "ubuntugis-unstable" do
   uri "ppa:ubuntugis/ubuntugis-unstable"
 end
 
+apt_repository "git-core" do
+  action repository_actions["git-core"]
+  uri "ppa:git-core/ppa"
+end
+
+apt_repository "maxmind" do
+  action repository_actions["maxmind"]
+  uri "ppa:maxmind/ppa"
+end
+
 apt_repository "openstreetmap" do
   action repository_actions["openstreetmap"]
   uri "ppa:osmadmins/ppa"
@@ -96,7 +106,7 @@ end
 apt_repository "management-component-pack" do
   action repository_actions["management-component-pack"]
   uri "https://downloads.linux.hpe.com/SDR/repo/mcp"
-  distribution "#{node[:lsb][:codename]}/current-gen9"
+  distribution "bionic/current-gen9"
   components ["non-free"]
   key "C208ADDE26C2B797"
 end
@@ -153,7 +163,28 @@ apt_repository "mediawiki" do
   uri "https://releases.wikimedia.org/debian"
   distribution "jessie-mediawiki"
   components ["main"]
-  key "90E9F83F22250DD7"
+  key "AF380A3036A03444"
+end
+
+apt_repository "docker" do
+  action repository_actions["docker"]
+  uri "https://download.docker.com/linux/ubuntu"
+  arch "amd64"
+  components ["stable"]
+  key "https://download.docker.com/linux/ubuntu/gpg"
+end
+
+apt_repository "grafana" do
+  action repository_actions["grafana"]
+  uri "https://packages.grafana.com/enterprise/deb"
+  distribution "stable"
+  components ["main"]
+  key "https://packages.grafana.com/gpg.key"
+end
+
+apt_repository "timescaledb" do
+  action repository_actions["timescaledb"]
+  uri "ppa:timescale/timescaledb-ppa"
 end
 
 package "unattended-upgrades"
@@ -168,7 +199,7 @@ if Dir.exist?("/usr/share/unattended-upgrades")
   file "/etc/apt/apt.conf.d/20auto-upgrades" do
     user "root"
     group "root"
-    mode 0o644
+    mode "644"
     content auto_upgrades
   end
 end
@@ -177,5 +208,5 @@ template "/etc/apt/apt.conf.d/60chef" do
   source "apt.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
index b0552bbc1907ebfcdacffde4f7ab9c3dedfe5925..730678e581cfe36b8e41213eaafe3f7fa1b2d59f 100644 (file)
@@ -3,3 +3,7 @@
 // Do automatic removal of new unused dependencies after the upgrade
 // (equivalent to apt-get autoremove)
 Unattended-Upgrade::Remove-Unused-Dependencies "<%= node[:apt][:unattended_upgrades][:remove_unused_dependencies] ? 'true' : 'false' %>";
+
+// Don't install recommended packages as we don't want to get
+// new postgres versions automatically
+APT::Install-Recommends "false";
index e572f7ced598e41f2b10d3607940ecab14d46dfb..d3d52ef7b6330be861e83c5334c2a35ed8f43019 100644 (file)
@@ -1,51 +1,49 @@
 # DO NOT EDIT - This file is being maintained by Chef
 
 deb http://<%= @archive_host %>/ubuntu/ <%= @codename %> main restricted
-deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %> main restricted
+deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %> main restricted
 
 ## Major bug fix updates produced after the final release of the
 ## distribution.
 deb http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates main restricted
-deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates main restricted
+deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates main restricted
 
 ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
 ## team. Also, please note that software in universe WILL NOT receive any
 ## review or updates from the Ubuntu security team.
 deb http://<%= @archive_host %>/ubuntu/ <%= @codename %> universe
-deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %> universe
+deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %> universe
 deb http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates universe
-deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates universe
+deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates universe
 
-## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu 
-## team, and may not be under a free licence. Please satisfy yourself as to 
-## your rights to use the software. Also, please note that software in 
+## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
+## team, and may not be under a free licence. Please satisfy yourself as to
+## your rights to use the software. Also, please note that software in
 ## multiverse WILL NOT receive any review or updates from the Ubuntu
 ## security team.
 deb http://<%= @archive_host %>/ubuntu/ <%= @codename %> multiverse
-deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %> multiverse
+deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %> multiverse
 deb http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates multiverse
-deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates multiverse
+deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %>-updates multiverse
 
-## Uncomment the following two lines to add software from the 'backports'
-## repository.
 ## N.B. software from this repository may not have been tested as
 ## extensively as that contained in the main release, although it includes
 ## newer versions of some applications which may provide useful features.
 ## Also, please note that software in backports WILL NOT receive any review
 ## or updates from the Ubuntu security team.
 deb http://<%= @archive_host %>/ubuntu/ <%= @codename %>-backports main restricted universe multiverse
-deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %>-backports main restricted universe multiverse
+deb-src http://<%= @archive_host %>/ubuntu/ <%= @codename %>-backports main restricted universe multiverse
 
 ## Uncomment the following two lines to add software from Canonical's
-## 'partner' repository. This software is not part of Ubuntu, but is
-## offered by Canonical and the respective vendors as a service to Ubuntu
-## users.
+## 'partner' repository.
+## This software is not part of Ubuntu, but is offered by Canonical and the
+## respective vendors as a service to Ubuntu users.
 # deb http://archive.canonical.com/ubuntu <%= @codename %> partner
 # deb-src http://archive.canonical.com/ubuntu <%= @codename %> partner
 
-deb http://security.ubuntu.com/ubuntu <%= @codename %>-security main restricted
-deb-src http://security.ubuntu.com/ubuntu <%= @codename %>-security main restricted
-deb http://security.ubuntu.com/ubuntu <%= @codename %>-security universe
-deb-src http://security.ubuntu.com/ubuntu <%= @codename %>-security universe
-deb http://security.ubuntu.com/ubuntu <%= @codename %>-security multiverse
-deb-src http://security.ubuntu.com/ubuntu <%= @codename %>-security multiverse
+deb http://security.ubuntu.com/ubuntu/ <%= @codename %>-security main restricted
+# deb-src http://security.ubuntu.com/ubuntu/ <%= @codename %>-security main restricted
+deb http://security.ubuntu.com/ubuntu/ <%= @codename %>-security universe
+# deb-src http://security.ubuntu.com/ubuntu/ <%= @codename %>-security universe
+deb http://security.ubuntu.com/ubuntu/ <%= @codename %>-security multiverse
+# deb-src http://security.ubuntu.com/ubuntu/ <%= @codename %>-security multiverse
index c0b8de57fac80d3d0e113116f78e07e7fc643d08..2773238abd6b254b931ad86345fafb1fda49502d 100644 (file)
@@ -1 +1,3 @@
 default[:stats][:sites] = []
+
+default[:accounts][:users][:osmbackup][:status] = :role
index c4f1bdabd113dd2fc0e7c9f346a8208e496a84ae..d5baa16641ad1dcb8a721fef4628ca37ac3b96b8 100644 (file)
@@ -6,3 +6,4 @@ description       "Installs and configures backup.openstreetmap.org"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
index 0204f56f294f6b558c22a26c59f2147687ccef85..a123a19ab8cb2e7b71dd3ad01fa9bc39e0480cfd 100644 (file)
@@ -17,6 +17,8 @@
 # limitations under the License.
 #
 
+include_recipe "accounts"
+
 package %w[
   perl
   libdate-calc-perl
@@ -25,18 +27,19 @@ package %w[
 directory "/store/backup" do
   owner "osmbackup"
   group "osmbackup"
-  mode 0o2755
+  mode "2755"
+  recursive true
 end
 
 cookbook_file "/usr/local/bin/expire-backups" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 template "/etc/cron.daily/expire-backups" do
   source "expire.cron.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
index 9f80b24c06a36e62a2b23efdd62cb63b04dd70c8..dc4f7e15ea74f394fc6d29a02f4c2a2bba6e5144 100644 (file)
@@ -2,7 +2,7 @@
 
 # DO NOT EDIT - This file is being maintained by Chef
 
-for prefix in chef-server chef-repository chef-git forum git lists munin osm-blog osm-donate osmf-crm osmf-ledgersmb wiki-wiki.osmfoundation.org osqa otrs sotm svn switch2osm trac wiki-board.osmfoundation.org wiki-dwg.osmfoundation.org wiki-wiki.openstreetmap.org
+for prefix in chef-server chef-repository chef-git forum git lists munin osm-blog osm-donate osmf-crm osmf-ledgersmb wiki-wiki.osmfoundation.org osqa otrs prometheus sotm svn switch2osm trac wiki-board.osmfoundation.org wiki-dwg.osmfoundation.org wiki-mwg.osmfoundation.org wiki-wiki.openstreetmap.org
 do
   /usr/local/bin/expire-backups --days=3 --weeks=3 --months=3 /store/backup $prefix
 done
index 087ef5802f4db2ff5eaac454f40f41675adcde8d..77c777e1a19e05d27babf440798f58e8639a8417 100644 (file)
@@ -31,34 +31,39 @@ end.flatten
 
 package "bind9"
 
-service "bind9" do
+service_name = if node[:lsb][:release].to_f < 20.04
+                 "bind9"
+               else
+                 "named"
+               end
+
+service service_name do
   action [:enable, :start]
-  supports :status => true, :restart => true, :reload => true
 end
 
 template "/etc/bind/named.conf.local" do
   source "named.local.erb"
   owner "root"
   group "root"
-  mode 0o644
-  notifies :restart, "service[bind9]"
+  mode "644"
+  notifies :restart, "service[#{service_name}]"
 end
 
 template "/etc/bind/named.conf.options" do
   source "named.options.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   variables :ipv4_clients => ipv4_clients, :ipv6_clients => ipv6_clients
-  notifies :restart, "service[bind9]"
+  notifies :restart, "service[#{service_name}]"
 end
 
 template "/etc/bind/db.10" do
   source "db.10.erb"
   owner "root"
   group "root"
-  mode 0o644
-  notifies :reload, "service[bind9]"
+  mode "644"
+  notifies :reload, "service[#{service_name}]"
 end
 
 firewall_rule "accept-dns-udp" do
index 78965844826e7838bc510d5368c0259a48cf5bed..2f80e2b13f78aa2437c9ae905650971a4c540a0e 100644 (file)
@@ -24,7 +24,7 @@ passwords = data_bag_item("blog", "passwords")
 directory "/srv/blog.openstreetmap.org" do
   owner "wordpress"
   group "wordpress"
-  mode 0o755
+  mode "755"
 end
 
 wordpress_site "blog.openstreetmap.org" do
@@ -38,12 +38,13 @@ wordpress_site "blog.openstreetmap.org" do
   urls "/casts" => "/srv/blog.openstreetmap.org/casts",
        "/images" => "/srv/blog.openstreetmap.org/images",
        "/static" => "/srv/blog.openstreetmap.org/static"
+  fpm_prometheus_port 11401
 end
 
 wordpress_theme "blog.openstreetmap.org-osmblog-wp-theme" do
   theme "osmblog-wp-theme"
   site "blog.openstreetmap.org"
-  repository "git://github.com/harry-wood/osmblog-wp-theme.git"
+  repository "https://github.com/harry-wood/osmblog-wp-theme.git"
 end
 
 wordpress_plugin "blog.openstreetmap.org-google-analytics-for-wordpress" do
@@ -65,6 +66,7 @@ wordpress_plugin "blog.openstreetmap.org-sitepress-multilingual-cms" do
   plugin "sitepress-multilingual-cms"
   site "blog.openstreetmap.org"
   repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
+  not_if { ENV["TEST_KITCHEN"] }
 end
 
 wordpress_plugin "blog.openstreetmap.org-wordpress-importer" do
@@ -74,7 +76,7 @@ end
 
 git "/srv/blog.openstreetmap.org/casts" do
   action :sync
-  repository "git://github.com/openstreetmap/opengeodata-podcasts.git"
+  repository "https://github.com/openstreetmap/opengeodata-podcasts.git"
   depth 1
   user "wordpress"
   group "wordpress"
@@ -82,7 +84,7 @@ end
 
 git "/srv/blog.openstreetmap.org/images" do
   action :sync
-  repository "git://github.com/openstreetmap/opengeodata-images.git"
+  repository "https://github.com/openstreetmap/opengeodata-images.git"
   depth 1
   user "wordpress"
   group "wordpress"
@@ -90,7 +92,7 @@ end
 
 git "/srv/blog.openstreetmap.org/static" do
   action :sync
-  repository "git://github.com/openstreetmap/opengeodata-static.git"
+  repository "https://github.com/openstreetmap/opengeodata-static.git"
   depth 1
   user "wordpress"
   group "wordpress"
@@ -110,6 +112,6 @@ template "/etc/cron.daily/blog-backup" do
   source "backup.cron.erb"
   owner "root"
   group "root"
-  mode 0o750
+  mode "750"
   variables :passwords => passwords
 end
index 557440ff412c910e5dd9cbe26a10fb354337c31a..bc6159666e79bac886e06f3c70bc21ca4faf4843 100644 (file)
@@ -10,13 +10,12 @@ mkdir $T/osm-blog-$D
 echo '[mysqldump]' > $T/mysqldump.opts
 echo 'user=osm-blog-user' >> $T/mysqldump.opts
 echo 'password=<%= @passwords["osm-blog-user"] %>' >> $T/mysqldump.opts
-mysqldump --defaults-file=$T/mysqldump.opts --opt osm-blog > $T/osm-blog-$D/osm-blog.sql
+mysqldump --defaults-file=$T/mysqldump.opts --opt --no-tablespaces osm-blog > $T/osm-blog-$D/osm-blog.sql
 ln -s /srv/blog.openstreetmap.org $T/osm-blog-$D/www
 
-export GZIP="--rsyncable -9"
 export RSYNC_RSH="ssh -ax"
 
-nice tar --create --gzip --dereference --directory=$T --warning=no-file-changed --file=$T/$B osm-blog-$D
+nice tar --create --dereference --directory=$T --warning=no-file-changed osm-blog-$D | nice gzip --rsyncable -9 > $T/$B
 nice rsync --preallocate --fuzzy $T/$B backup::backup
 
 rm -rf $T
index 6f2b7dfc6dc5aa667340907cc79daa1b24d9674d..19d88bcfec8c8f80a8ed933c2e449b70d9ba62df 100644 (file)
@@ -6,5 +6,6 @@ description       "Configures server-info web site"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
 depends           "git"
index d08fc482cb410b4c4ab27f4f2ba736c538aa8dd8..165befb5e6f391d0f17b40c202bfa590c97b7f79 100644 (file)
 # limitations under the License.
 #
 
+include_recipe "accounts"
 include_recipe "apache"
 include_recipe "git"
 
-package %w[
-  ruby
-  ruby-dev
+ruby_version = if node[:lsb][:release].to_f < 20.04
+                 "2.5"
+               else
+                 "2.7"
+               end
+
+package %W[
+  ruby#{ruby_version}
+  ruby#{ruby_version}-dev
   make
   gcc
+  g++
   libsqlite3-dev
 ]
 
-gem_package "bundler"
+gem_package "bundler#{ruby_version}" do
+  package_name "bundler"
+  version "~> 2.1.4"
+  gem_binary "gem#{ruby_version}"
+  options "--format-executable"
+end
 
 directory "/srv/blogs.openstreetmap.org" do
   owner "blogs"
   group "blogs"
-  mode 0o755
+  mode "755"
 end
 
 git "/srv/blogs.openstreetmap.org" do
   action :sync
-  repository "git://github.com/gravitystorm/blogs.osm.org.git"
+  repository "https://github.com/gravitystorm/blogs.osm.org.git"
+  depth 1
   user "blogs"
   group "blogs"
-  notifies :run, "execute[/srv/blogs.openstreetmap.org/Gemfile]", :immediate
+  notifies :run, "execute[/srv/blogs.openstreetmap.org/Gemfile]", :immediately
 end
 
 execute "/srv/blogs.openstreetmap.org/Gemfile" do
   action :nothing
-  command "bundle install"
+  command "bundle#{ruby_version} install --deployment"
   cwd "/srv/blogs.openstreetmap.org"
-  user "root"
-  group "root"
-  notifies :run, "execute[/srv/blogs.openstreetmap.org]", :immediate
+  user "blogs"
+  group "blogs"
+  notifies :run, "execute[/srv/blogs.openstreetmap.org]", :immediately
 end
 
 execute "/srv/blogs.openstreetmap.org" do
   action :nothing
-  command "bundle exec /usr/local/bin/pluto build -t osm -o build"
+  command "bundle#{ruby_version} exec pluto build -t osm -o build"
   cwd "/srv/blogs.openstreetmap.org"
   user "blogs"
   group "blogs"
@@ -72,9 +86,17 @@ apache_site "blogs.openstreetmap.org" do
   variables :aliases => ["blogs.osm.org"]
 end
 
-template "/etc/cron.d/blogs" do
-  source "cron.erb"
+template "/usr/local/bin/blogs-update" do
+  source "blogs-update.erb"
   owner "root"
   group "root"
-  mode "0644"
+  mode "0755"
+  variables :ruby_version => ruby_version
+end
+
+cron_d "blogs" do
+  minute "*/30"
+  user "blogs"
+  command "/usr/local/bin/blogs-update"
+  mailto "admins@openstreetmap.org"
 end
diff --git a/cookbooks/blogs/templates/default/blogs-update.erb b/cookbooks/blogs/templates/default/blogs-update.erb
new file mode 100644 (file)
index 0000000..ef880cd
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+cd /srv/blogs.openstreetmap.org
+
+/usr/local/bin/bundle<%= @ruby_version %> exec pluto \
+       --quieter \
+       --config=/srv/blogs.openstreetmap.org build \
+       --dbpath=/srv/blogs.openstreetmap.org \
+       --template=osm \
+       --output=/srv/blogs.openstreetmap.org/build \
+       /srv/blogs.openstreetmap.org/planet.ini > log.$$ 2>&1
+
+if [ $? -ne 0 ]
+then
+    cat log.$$
+fi
+
+rm -f log.$$
diff --git a/cookbooks/blogs/templates/default/cron.erb b/cookbooks/blogs/templates/default/cron.erb
deleted file mode 100644 (file)
index c2d6dfb..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-
-MAILTO=admins@openstreetmap.org
-
-*/30 * * * * blogs cd /srv/blogs.openstreetmap.org; bundle exec /usr/local/bin/pluto --quieter --config=/srv/blogs.openstreetmap.org build --dbpath=/srv/blogs.openstreetmap.org --template=osm --output=/srv/blogs.openstreetmap.org/build /srv/blogs.openstreetmap.org/planet.ini > /dev/null
diff --git a/cookbooks/cgiirc/README.md b/cookbooks/cgiirc/README.md
deleted file mode 100644 (file)
index 49eeb3d..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# Cgiirc Cookbook
-
-This cookbook installs and configures the `cgiirc` program that powers the
-web interface to the OSM IRC channels, found at irc.openstreetmap.org
diff --git a/cookbooks/cgiirc/templates/default/cgiirc.config.erb b/cookbooks/cgiirc/templates/default/cgiirc.config.erb
deleted file mode 100644 (file)
index 794b4cb..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-
-# CGI:IRC configuration file.
-#
-# Check /usr/share/doc/cgiirc/examples/cgiirc.config.full.gz
-# for more details.
-
-# Configure defaults
-default_server = irc.oftc.net
-default_port = 6667
-default_channel = #osm,#osm-dev,#osm-ewg,#osm-cwg,#osm-ar,#osm-asia,#osm-au,#osm-br,#osm-bw,#osm-by,#osm-ca,#osm-ch,#osm-cz,#osm-de,#osm-dk,#osm-es,#osm-fi,#osm-fr,#osm-gb,#osm-gr,#osm-gsoc,#osm-ht,#osm-ie,#osm-it,#osm-ke,#osm-latam,#osm-local,#osm-lv,#osm-nl,#osm-no,#osm-nominatim,#osm-pl,#osm-pt,#osm-ru,#osm.se,#osm-strategic,#osm-ua,#osm-us,#osm-za,#osm-zh,#osmf-gm,#osrm,#openrailwaymap,#hot
-default_name = CGI:IRC User
-default_nick = CGI???
-
-# Path to images
-image_path = /images
-
-# Paths to CGI scripts
-script_nph = nph-irc.cgi
-script_form = client-perl.cgi
-script_login = irc.cgi
-
-# Access control file
-ip_access_file = ipaccess
diff --git a/cookbooks/cgiirc/templates/default/ipaccess.erb b/cookbooks/cgiirc/templates/default/ipaccess.erb
deleted file mode 100644 (file)
index ba2851c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-
-# CGI:IRC ipaccess file. (For CGI:IRC versions from 0.5.3).
-#
-# Check /usr/share/doc/cgiirc/examples/ipaccess.example
-# for more details.
-
-<% @blocks.each do |name,addresses| -%>
-# Block <%= name %>
-<% addresses.each do |address| -%>
-<%= address %> 0
-<% end -%>
-
-<% end -%>
-# Allow everybody.
-0.0.0.0/0
index 2cac140f19e7489c274d0c24ca2b21de79b6ecd9..41b03e63adf247b73c9ebb2ac530506811d5ffe1 100644 (file)
@@ -5,4 +5,4 @@ default[:apt][:sources] = node[:apt][:sources] | ["opscode"]
 default[:chef][:server][:version] = "12.17.33"
 
 # Set the default client version
-default[:chef][:client][:version] = "14.12.9"
+default[:chef][:client][:version] = "16.8.14"
diff --git a/cookbooks/chef/libraries/git.rb b/cookbooks/chef/libraries/git.rb
new file mode 100644 (file)
index 0000000..176613d
--- /dev/null
@@ -0,0 +1,13 @@
+module OpenStreetMap
+  module Provider
+    module Git
+      def git(*args, **run_opts)
+        args.push("--force") if args.first == "fetch" && args.last == "--tags"
+
+        super(args, **run_opts)
+      end
+    end
+  end
+end
+
+Chef::Provider::Git.prepend(OpenStreetMap::Provider::Git)
diff --git a/cookbooks/chef/libraries/persistent_token.rb b/cookbooks/chef/libraries/persistent_token.rb
new file mode 100644 (file)
index 0000000..8299e85
--- /dev/null
@@ -0,0 +1,20 @@
+require "digest"
+
+class Chef
+  module Mixin
+    module PersistentToken
+      def persistent_token(*args)
+        sha256 = Digest::SHA256.new
+        sha256.update(node[:machine_id])
+        args.each do |arg|
+          sha256.update(arg)
+        end
+        sha256.hexdigest
+      end
+    end
+  end
+
+  class Recipe
+    include Chef::Mixin::PersistentToken
+  end
+end
index cbcce026a8c772268d8eb9c32ae5d87f7b0848dd..8e9f1e3d280295f1b646ff90ebad74f21fc5f107 100644 (file)
@@ -44,6 +44,19 @@ class Chef
         command = scm(:info)
         shell_out!(command, run_options(:cwd => cwd, :returns => [0, 1])).stdout
       end
+
+      def revision_int
+        @revision_int ||= begin
+          if new_resource.revision =~ /^\d+$/
+            new_resource.revision
+          else
+            command = scm(:info, new_resource.repository, new_resource.svn_info_args, authentication, "-r#{new_resource.revision}")
+            svn_info = shell_out!(command, run_options(:returns => [0, 1])).stdout
+
+            extract_revision_info(svn_info)
+          end
+        end
+      end
     end
   end
 end
index f2f0101c08b22d7c8a30b63e582545a57425b628..61ac42415fd2a36aeb08c168da46c78fa22e3a79 100644 (file)
 # limitations under the License.
 #
 
+cache_dir = Chef::Config[:file_cache_path]
+
 chef_version = node[:chef][:client][:version]
 chef_package = "chef_#{chef_version}-1_amd64.deb"
 
 directory "/var/cache/chef" do
-  owner "root"
-  group "root"
-  mode 0o755
+  action :delete
+  recursive true
 end
 
-Dir.glob("/var/cache/chef/chef_*.deb").each do |deb|
-  next if deb == "/var/cache/chef/#{chef_package}"
+Dir.glob("#{cache_dir}/chef_*.deb").each do |deb|
+  next if deb == "#{cache_dir}/#{chef_package}"
 
   file deb do
     action :delete
@@ -35,91 +36,96 @@ Dir.glob("/var/cache/chef/chef_*.deb").each do |deb|
   end
 end
 
-remote_file "/var/cache/chef/#{chef_package}" do
+remote_file "#{cache_dir}/#{chef_package}" do
   source "https://packages.chef.io/files/stable/chef/#{chef_version}/ubuntu/#{node[:lsb][:release]}/#{chef_package}"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   backup false
   ignore_failure true
 end
 
 dpkg_package "chef" do
-  source "/var/cache/chef/#{chef_package}"
+  source "#{cache_dir}/#{chef_package}"
   version "#{chef_version}-1"
 end
 
 directory "/etc/chef" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 template "/etc/chef/client.rb" do
   source "client.rb.erb"
   owner "root"
   group "root"
-  mode 0o640
+  mode "640"
 end
 
 file "/etc/chef/client.pem" do
   owner "root"
   group "root"
-  mode 0o400
+  mode "400"
 end
 
 template "/etc/chef/report.rb" do
   source "report.rb.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 template "/etc/logrotate.d/chef" do
   source "logrotate.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 directory "/etc/chef/trusted_certs" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 template "/etc/chef/trusted_certs/verisign.pem" do
   source "verisign.pem.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 directory node[:ohai][:plugin_dir] do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 directory "/var/log/chef" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 systemd_service "chef-client" do
+  description "Chef client"
+  exec_start "/usr/bin/chef-client"
+end
+
+systemd_timer "chef-client" do
   description "Chef client"
   after "network.target"
-  exec_start "/usr/bin/chef-client -i 1800 -s 20"
-  restart "on-failure"
+  on_active_sec 60
+  on_unit_inactive_sec 25 * 60
+  randomized_delay_sec 10 * 60
 end
 
-service "chef-client" do
+service "chef-client.timer" do
   action [:enable, :start]
-  restart_command "systemctl kill --signal=TERM chef-client.service"
-  supports :status => true, :restart => true, :reload => true
-  subscribes :restart, "dpkg_package[chef]"
-  subscribes :restart, "template[/etc/init/chef-client.conf]"
-  subscribes :restart, "template[/etc/chef/client.rb]"
-  subscribes :restart, "template[/etc/chef/report.rb]"
+end
+
+service "chef-client.service" do
+  action :disable
+  subscribes :stop, "service[chef-client.timer]"
 end
index 28d0b2f39367ca85bab94406a9407a6dbfb93c20..d5d8d2bc2817c6eeb759ca27f012672ea36fa193 100644 (file)
@@ -21,10 +21,14 @@ include_recipe "git"
 
 keys = data_bag_item("chef", "keys")
 
+chef_gem "bundler" do
+  version ">= 2.1.4"
+end
+
 directory "/var/lib/chef" do
   owner "chefrepo"
   group "chefrepo"
-  mode 0o2775
+  mode "2775"
 end
 
 %w[public private].each do |repository|
@@ -41,28 +45,28 @@ end
   directory "/var/lib/chef/#{repository}/.chef" do
     owner "chefrepo"
     group "chefrepo"
-    mode 0o2775
+    mode "2775"
   end
 
   file "/var/lib/chef/#{repository}/.chef/client.pem" do
     content keys["git"].join("\n")
     owner "chefrepo"
     group "chefrepo"
-    mode 0o660
+    mode "660"
   end
 
   cookbook_file "/var/lib/chef/#{repository}/.chef/knife.rb" do
     source "knife.rb"
     owner "chefrepo"
     group "chefrepo"
-    mode 0o660
+    mode "660"
   end
 
   template "#{repository_directory}/hooks/post-receive" do
     source "post-receive.erb"
     owner "chefrepo"
     group "chefrepo"
-    mode 0o750
+    mode "750"
     variables :repository => repository
   end
 end
index eb2a33ae4a31ecb18178e791687aa57bff04f6b1..cd4968b734c05452ff75d0d8058a8ac71b615d1c 100644 (file)
 #
 
 include_recipe "apache"
+include_recipe "munin"
 
+# cache_dir = Chef::Config[:file_cache_path]
+#
 # chef_version = node[:chef][:server][:version]
 # chef_package = "chef-server-core_#{chef_version}-1_amd64.deb"
 #
-# directory "/var/cache/chef" do
-#   owner "root"
-#   group "root"
-#   mode 0755
-# end
+# Dir.glob("#{cache_dir}/chef-server-core_*.deb").each do |deb|
+#   next if deb == "#{cache_dir}/#{chef_package}"
 #
-# Dir.glob("/var/cache/chef/chef-server-core_*.deb").each do |deb|
-#   next if deb == "/var/cache/chef/#{chef_package}"
-
 #   file deb do
 #     action :delete
 #     backup false
 #   end
 # end
 #
-# remote_file "/var/cache/chef/#{chef_package}" do
+# remote_file "#{cache_dir}/#{chef_package}" do
 #   source "https://packages.chef.io/files/stable/chef-server/#{chef_version}/ubuntu/16.04/#{chef_package}"
 #   owner "root"
 #   group "root"
@@ -46,7 +43,7 @@ include_recipe "apache"
 # end
 #
 # dpkg_package "chef-server-core" do
-#   source "/var/cache/chef/#{chef_package}"
+#   source "#{cache_dir}/#{chef_package}"
 #   version "#{chef_version}-1"
 #   notifies :run, "execute[chef-server-reconfigure]"
 # end
@@ -55,7 +52,7 @@ template "/etc/opscode/chef-server.rb" do
   source "server.rb.erb"
   owner "root"
   group "root"
-  mode 0o640
+  mode "640"
   notifies :run, "execute[chef-server-reconfigure]"
 end
 
@@ -101,7 +98,7 @@ template "/etc/cron.daily/chef-server-backup" do
   source "server-backup.cron.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 munin_plugin "chef_status"
diff --git a/cookbooks/chef/templates/default/chef-client.conf.erb b/cookbooks/chef/templates/default/chef-client.conf.erb
deleted file mode 100644 (file)
index 9414e05..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-# chef-client
-#
-# Startup script for chef-client
-
-description "starts up chef-client in daemon mode"
-
-start on (net-device-up
-          and local-filesystems
-          and runlevel [2345])
-stop on runlevel [!2345]
-
-script
-        exec /usr/bin/chef-client -i 1800 -s 20
-end script
-
-respawn
index 5d1f463930de23870f0273116e749d3218690e62..796b276c57e1704dcf2dc5947d0cff4576456c01 100644 (file)
@@ -9,6 +9,10 @@
 
 Encoding.default_external = Encoding::UTF_8
 
+# Accept the license
+
+chef_license "accept"
+
 # Log at level info
 
 log_level :info
@@ -33,6 +37,10 @@ chef_server_url "https://chef.openstreetmap.org/organizations/openstreetmap"
 
 ohai.plugin_path << "<%= node[:ohai][:plugin_dir] %>"
 
+# Enable some optional ohai plugins
+
+ohai.optional_plugins = %w[Passwd]
+
 # Load supporting code for report handlers
 
 require "/etc/chef/report"
index 20e32ef4fccea228512250a50e68e2aaaf29e1a8..4265d0660cb18412a5070ee8ee44152cb024210f 100644 (file)
@@ -31,6 +31,10 @@ class Chef
 
         require "mail"
 
+        Mail.defaults do
+          delivery_method :exim, :location => "/usr/sbin/exim"
+        end
+
         Mail.deliver do
           to to_address
           from from_address
index 048bc99e9679e2b41ad5598f1d730f18056e8ec4..04e6c0e0c2363c1e0d61ad43f8b1dcd2d3da0fb9 100644 (file)
@@ -10,9 +10,7 @@ chmod g+rwx $T $T/chef-server-$D
 sudo -u opscode-pgsql /opt/opscode/embedded/bin/pg_dumpall --file=$T/chef-server-$D/chef.dmp --clean
 ln -s /var/opt/opscode/bookshelf/data $T/chef-server-$D/bookshelf
 
-export GZIP="--rsyncable -9"
-
-nice tar --create --gzip --dereference --directory=$T --file=$T/$B chef-server-$D
+nice tar --create --dereference --directory=$T chef-server-$D | nice gzip --rsyncable -9 > $T/$B
 nice rsync --preallocate --fuzzy $T/$B backup::backup
 
 rm -rf $T
index d273ae4bd5db8d02ee19590d8acb7fac8a04e011..f0143f6f720d0c30a4458f5d8bb54e0d8e8337ed 100644 (file)
@@ -1,37 +1,37 @@
-default[:civicrm][:version] = "5.14.0"
+default[:civicrm][:version] = "5.34.0"
 
 default[:civicrm][:extensions][:cividiscount][:name] = "org.civicrm.module.cividiscount"
-default[:civicrm][:extensions][:cividiscount][:repository] = "git://github.com/dlobo/org.civicrm.module.cividiscount.git"
-default[:civicrm][:extensions][:cividiscount][:revision] = "3.7"
+default[:civicrm][:extensions][:cividiscount][:repository] = "https://github.com/dlobo/org.civicrm.module.cividiscount.git"
+default[:civicrm][:extensions][:cividiscount][:revision] = "3.8.2"
 
 default[:civicrm][:extensions][:osm][:name] = "de.systopia.osm"
-default[:civicrm][:extensions][:osm][:repository] = "git://github.com/systopia/de.systopia.osm.git"
+default[:civicrm][:extensions][:osm][:repository] = "https://github.com/systopia/de.systopia.osm.git"
 default[:civicrm][:extensions][:osm][:revision] = "1.2.1"
 
 default[:civicrm][:extensions][:emailapi][:name] = "org.civicoop.emailapi"
-default[:civicrm][:extensions][:emailapi][:repository] = "git://github.com/CiviCooP/org.civicoop.emailapi.git"
+default[:civicrm][:extensions][:emailapi][:repository] = "https://github.com/CiviCooP/org.civicoop.emailapi.git"
 default[:civicrm][:extensions][:emailapi][:revision] = "1.19"
 
 default[:civicrm][:extensions][:civiruleshttppost][:name] = "org.civicoop.civiruleshttppost"
-default[:civicrm][:extensions][:civiruleshttppost][:repository] = "git://github.com/CiviCooP/org.civicoop.civiruleshttppost.git"
+default[:civicrm][:extensions][:civiruleshttppost][:repository] = "https://github.com/CiviCooP/org.civicoop.civiruleshttppost.git"
 default[:civicrm][:extensions][:civiruleshttppost][:revision] = "e2c7de5f0fee319b9fca8adb1d1e122202bd2bec"
 
 default[:civicrm][:extensions][:civirules][:name] = "org.civicoop.civirules"
 default[:civicrm][:extensions][:civirules][:repository] = "https://lab.civicrm.org/extensions/civirules.git"
-default[:civicrm][:extensions][:civirules][:revision] = "2.7"
-
-default[:civicrm][:extensions][:stripe][:name] = "com.drastikbydesign.stripe"
-default[:civicrm][:extensions][:stripe][:repository] = "git://github.com/drastik/com.drastikbydesign.stripe.git"
-default[:civicrm][:extensions][:stripe][:revision] = "4.7.3"
+default[:civicrm][:extensions][:civirules][:revision] = "2.22"
 
 default[:civicrm][:extensions][:mailchimp][:name] = "uk.co.vedaconsulting.mailchimp"
-default[:civicrm][:extensions][:mailchimp][:repository] = "git://github.com/veda-consulting/uk.co.vedaconsulting.mailchimp.git"
-default[:civicrm][:extensions][:mailchimp][:revision] = "v2.0.1"
+default[:civicrm][:extensions][:mailchimp][:repository] = "https://github.com/veda-consulting/uk.co.vedaconsulting.mailchimp.git"
+default[:civicrm][:extensions][:mailchimp][:revision] = "124083b29ab28246883bc83f207498a85f01ecde"
 
 default[:civicrm][:extensions][:username][:name] = "org.openstreetmap.username"
-default[:civicrm][:extensions][:username][:repository] = "git://github.com/grischard/org.openstreetmap.username.git"
+default[:civicrm][:extensions][:username][:repository] = "https://github.com/grischard/org.openstreetmap.username.git"
 default[:civicrm][:extensions][:username][:revision] = "master"
 
 default[:civicrm][:extensions][:donotsendreportemail][:name] = "org.civicrm.donotsendreportemail"
-default[:civicrm][:extensions][:donotsendreportemail][:repository] = "git://github.com/pradpnayak/org.civicrm.donotsendreportemail.git"
+default[:civicrm][:extensions][:donotsendreportemail][:repository] = "https://github.com/pradpnayak/org.civicrm.donotsendreportemail.git"
 default[:civicrm][:extensions][:donotsendreportemail][:revision] = "3b31c2e0c62183872c7ecd244395fb8dcfbd5dbb"
+
+default[:civicrm][:extensions][:shoreditch][:name] = "org.civicrm.shoreditch"
+default[:civicrm][:extensions][:shoreditch][:repository] = "https://github.com/civicrm/org.civicrm.shoreditch.git"
+default[:civicrm][:extensions][:shoreditch][:revision] = "1.0.0-beta.1"
index 46c17d5040d2ab1af156c814a9f2710fde3b432d..a8881fc0d898773faf33a35af7216a4e5eab2ed5 100644 (file)
 include_recipe "wordpress"
 include_recipe "mysql"
 
-package "wkhtmltopdf"
+package %w[
+  php-xml
+  php-curl
+  rsync
+  unzip
+  wkhtmltopdf
+  php-bcmath
+]
+
+cache_dir = Chef::Config[:file_cache_path]
 
 passwords = data_bag_item("civicrm", "passwords")
 
@@ -40,11 +49,12 @@ wordpress_site "join.osmfoundation.org" do
   database_name "civicrm"
   database_user "civicrm"
   database_password database_password
+  fpm_prometheus_port 11301
 end
 
 wordpress_theme "osmblog-wp-theme" do
   site "join.osmfoundation.org"
-  repository "git://github.com/harry-wood/osmblog-wp-theme.git"
+  repository "https://github.com/harry-wood/osmblog-wp-theme.git"
 end
 
 wordpress_plugin "registration-honeypot" do
@@ -54,55 +64,60 @@ end
 wordpress_plugin "sitepress-multilingual-cms" do
   site "join.osmfoundation.org"
   repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
+  not_if { ENV["TEST_KITCHEN"] }
 end
 
 wordpress_plugin "contact-form-7" do
   site "join.osmfoundation.org"
 end
 
+wordpress_plugin "civicrm-admin-utilities" do
+  site "join.osmfoundation.org"
+end
+
 civicrm_version = node[:civicrm][:version]
 civicrm_directory = "/srv/join.osmfoundation.org/wp-content/plugins/civicrm"
 
 directory "/opt/civicrm-#{civicrm_version}" do
   owner "wordpress"
   group "wordpress"
-  mode 0o755
+  mode "755"
 end
 
-remote_file "/var/cache/chef/civicrm-#{civicrm_version}-wordpress.zip" do
+remote_file "#{cache_dir}/civicrm-#{civicrm_version}-wordpress.zip" do
   action :create_if_missing
   source "https://download.civicrm.org/civicrm-#{civicrm_version}-wordpress.zip"
   owner "wordpress"
   group "wordpress"
-  mode 0o644
+  mode "644"
   backup false
 end
 
-remote_file "/var/cache/chef/civicrm-#{civicrm_version}-l10n.tar.gz" do
+remote_file "#{cache_dir}/civicrm-#{civicrm_version}-l10n.tar.gz" do
   action :create_if_missing
   source "https://download.civicrm.org/civicrm-#{civicrm_version}-l10n.tar.gz"
   owner "wordpress"
   group "wordpress"
-  mode 0o644
+  mode "644"
   backup false
 end
 
-execute "/var/cache/chef/civicrm-#{civicrm_version}-wordpress.zip" do
+execute "#{cache_dir}/civicrm-#{civicrm_version}-wordpress.zip" do
   action :nothing
-  command "unzip -qq /var/cache/chef/civicrm-#{civicrm_version}-wordpress.zip"
+  command "unzip -o -qq #{cache_dir}/civicrm-#{civicrm_version}-wordpress.zip"
   cwd "/opt/civicrm-#{civicrm_version}"
   user "wordpress"
   group "wordpress"
-  subscribes :run, "remote_file[/var/cache/chef/civicrm-#{civicrm_version}-wordpress.zip]", :immediately
+  subscribes :run, "remote_file[#{cache_dir}/civicrm-#{civicrm_version}-wordpress.zip]", :immediately
 end
 
-execute "/var/cache/chef/civicrm-#{civicrm_version}-l10n.tar.gz" do
+execute "#{cache_dir}/civicrm-#{civicrm_version}-l10n.tar.gz" do
   action :nothing
-  command "tar -zxf /var/cache/chef/civicrm-#{civicrm_version}-l10n.tar.gz"
+  command "tar -zxf #{cache_dir}/civicrm-#{civicrm_version}-l10n.tar.gz"
   cwd "/opt/civicrm-#{civicrm_version}/civicrm"
   user "wordpress"
   group "wordpress"
-  subscribes :run, "remote_file[/var/cache/chef/civicrm-#{civicrm_version}-l10n.tar.gz]", :immediately
+  subscribes :run, "remote_file[#{cache_dir}/civicrm-#{civicrm_version}-l10n.tar.gz]", :immediately
 end
 
 execute "/opt/civicrm-#{civicrm_version}/civicrm" do
@@ -110,14 +125,14 @@ execute "/opt/civicrm-#{civicrm_version}/civicrm" do
   command "rsync --archive --delete /opt/civicrm-#{civicrm_version}/civicrm/ #{civicrm_directory}"
   user "wordpress"
   group "wordpress"
-  subscribes :run, "execute[/var/cache/chef/civicrm-#{civicrm_version}-wordpress.zip]", :immediately
-  subscribes :run, "execute[/var/cache/chef/civicrm-#{civicrm_version}-l10n.tar.gz]", :immediately
+  subscribes :run, "execute[#{cache_dir}/civicrm-#{civicrm_version}-wordpress.zip]", :immediately
+  subscribes :run, "execute[#{cache_dir}/civicrm-#{civicrm_version}-l10n.tar.gz]", :immediately
 end
 
-directory "/srv/join.osmfoundation.org/wp-content/plugins/files" do
+directory "/srv/join.osmfoundation.org/wp-content/uploads" do
   owner "www-data"
   group "www-data"
-  mode 0o755
+  mode "755"
 end
 
 extensions_directory = "/srv/join.osmfoundation.org/wp-content/plugins/civicrm-extensions"
@@ -125,7 +140,7 @@ extensions_directory = "/srv/join.osmfoundation.org/wp-content/plugins/civicrm-e
 directory extensions_directory do
   owner "wordpress"
   group "wordpress"
-  mode 0o755
+  mode "755"
 end
 
 node[:civicrm][:extensions].each_value do |details|
@@ -149,10 +164,9 @@ settings = edit_file "#{civicrm_directory}/civicrm/templates/CRM/common/civicrm.
   line.gsub!(/%%dbHost%%/, "localhost")
   line.gsub!(/%%dbName%%/, "civicrm")
   line.gsub!(/%%crmRoot%%/, "#{civicrm_directory}/civicrm/")
-  line.gsub!(/%%templateCompileDir%%/, "/srv/join.osmfoundation.org/wp-content/plugins/files/civicrm/templates_c/")
+  line.gsub!(/%%templateCompileDir%%/, "/srv/join.osmfoundation.org/wp-content/uploads/civicrm/templates_c/")
   line.gsub!(/%%baseURL%%/, "http://join.osmfoundation.org/")
   line.gsub!(/%%siteKey%%/, site_key)
-  line.gsub!(%r{// *(.*'ext_repo_url'.*)$}, "\\1")
   line.gsub!(%r{// *define\('CIVICRM_CMSDIR', '/path/to/install/root/'\);}, "define('CIVICRM_CMSDIR', '/srv/join.osmfoundation.org');")
 
   line
@@ -161,22 +175,21 @@ end
 file "#{civicrm_directory}/civicrm.settings.php" do
   owner "wordpress"
   group "wordpress"
-  mode 0o644
+  mode "644"
   content settings
 end
 
-template "/etc/cron.d/osmf-crm" do
-  source "cron.erb"
-  owner "root"
-  group "root"
-  mode 0o600
-  variables :directory => civicrm_directory, :passwords => passwords
+cron_d "osmf-crm" do
+  minute "*/15"
+  user "www-data"
+  command "php #{civicrm_directory}/civicrm/bin/cli.php -s join.osmfoundation.org -u batch -p \"#{passwords['batch']}\" -e Job -a execute 2>&1 | egrep -v '^PHP (Deprecated|Warning):'"
+  mailto "admins@openstreetmap.org"
 end
 
 template "/etc/cron.daily/osmf-crm-backup" do
   source "backup.cron.erb"
   owner "root"
   group "root"
-  mode 0o750
+  mode "750"
   variables :passwords => passwords
 end
index 61bb4cd453898600d7414bddc15268004a6ed591..29fc2ba1b4b891d4e440cc8121a230a2bafc151e 100644 (file)
@@ -10,13 +10,12 @@ mkdir $T/osmf-crm-$D
 echo '[mysqldump]' > $T/mysqldump.opts
 echo 'user=civicrm' >> $T/mysqldump.opts
 echo 'password=<%= @passwords["database"] %>' >> $T/mysqldump.opts
-mysqldump --defaults-file=$T/mysqldump.opts --opt --skip-lock-tables civicrm > $T/osmf-crm-$D/civicrm.sql
+mysqldump --defaults-file=$T/mysqldump.opts --opt --skip-lock-tables --no-tablespaces civicrm > $T/osmf-crm-$D/civicrm.sql
 ln -s /srv/join.osmfoundation.org $T/osmf-crm-$D/www
 
-export GZIP="--rsyncable -9"
 export RSYNC_RSH="ssh -ax"
 
-nice tar --create --gzip --dereference --directory=$T --file=$T/$B osmf-crm-$D
+nice tar --create --dereference --directory=$T osmf-crm-$D | nice gzip --rsyncable -9 > $T/$B
 nice rsync --preallocate --fuzzy $T/$B backup::backup
 
 rm -rf $T
diff --git a/cookbooks/civicrm/templates/default/cron.erb b/cookbooks/civicrm/templates/default/cron.erb
deleted file mode 100644 (file)
index 22c3631..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-
-MAILTO=admins@openstreetmap.org
-
-*/15 * * * * www-data php <%= @directory %>/civicrm/bin/cli.php -s join.osmfoundation.org -u batch -p "<%= @passwords["batch"] %>" -e Job -a execute 2>&1 | egrep -v '^PHP (Deprecated|Warning):'
index 8e07f4fb76f23a8c597c4dd7f42f9134c0e388bf..f6dd24a5c8af5b5634eee0aba5c23f800dbee1a9 100644 (file)
@@ -27,7 +27,17 @@ template "/etc/clamav-unofficial-sigs.conf.d/50-chef.conf" do
   source "clamav-unofficial-sigs.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
+end
+
+execute "freshclam" do
+  command "/usr/bin/freshclam"
+  user "clamav"
+  group "clamav"
+  not_if do
+    ::File.exist?("/var/lib/clamav/daily.cld") ||
+      ::File.exist?("/var/lib/clamav/daily.cvd")
+  end
 end
 
 service "clamav-daemon" do
diff --git a/cookbooks/db/attributes/default.rb b/cookbooks/db/attributes/default.rb
new file mode 100644 (file)
index 0000000..1b674e3
--- /dev/null
@@ -0,0 +1,3 @@
+default[:db][:cluster] = "9.5/main"
+
+default[:postgresql][:versions] |= ["9.5"]
index 092949cb0ca4642268e88b68c4f0e94636c4f80d..aadfe47dbab448723064f2f3ad42022e6004dfb5 100644 (file)
@@ -6,7 +6,8 @@ description       "Installs and configures database servers"
 
 version           "1.0.0"
 supports          "ubuntu"
-depends           "postgresql"
-depends           "web"
+depends           "accounts"
 depends           "git"
+depends           "postgresql"
 depends           "python"
+depends           "web"
index 5a814392a3243d482e2cd90a5ef8bfb11bfa0943..0fe004d20f823fd4ef848f55322a594d14d611f4 100644 (file)
@@ -21,12 +21,14 @@ template "/usr/local/bin/backup-db" do
   source "backup-db.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
-template "/etc/cron.d/backup-db" do
-  source "backup.cron.erb"
-  owner "root"
-  group "root"
-  mode 0o644
+cron_d "backup-db" do
+  minute "00"
+  hour "02"
+  weekday "1"
+  user "osmbackup"
+  command "/usr/local/bin/backup-db"
+  mailto "admins@openstreetmap.org"
 end
index ee9d0089f65f13ce799b411def26b481414a9c0a..617392701f955f0c31a96f543be0683a4c72b447 100644 (file)
 # limitations under the License.
 #
 
-include_recipe "postgresql"
+include_recipe "accounts"
 include_recipe "git"
+include_recipe "postgresql"
 include_recipe "python"
 
 passwords = data_bag_item("db", "passwords")
 wal_secrets = data_bag_item("db", "wal-secrets")
 
+ruby_version = node[:passenger][:ruby_version]
+db_version = node[:db][:cluster].split("/").first
+pg_config = "/usr/lib/postgresql/#{db_version}/bin/pg_config"
+function_directory = "/srv/www.openstreetmap.org/rails/db/functions/#{db_version}"
+
 postgresql_munin "openstreetmap" do
   cluster node[:db][:cluster]
   database "openstreetmap"
@@ -31,16 +37,17 @@ end
 
 directory "/srv/www.openstreetmap.org" do
   group "rails"
-  mode 0o2775
+  mode "2775"
 end
 
 rails_port "www.openstreetmap.org" do
-  ruby "2.5"
+  ruby ruby_version
   directory "/srv/www.openstreetmap.org/rails"
   user "rails"
   group "rails"
   repository "https://git.openstreetmap.org/public/rails.git"
   revision "live"
+  build_assets false
   database_host "localhost"
   database_name "openstreetmap"
   database_username "openstreetmap"
@@ -48,19 +55,15 @@ rails_port "www.openstreetmap.org" do
   gpx_dir "/store/rails/gpx"
 end
 
-db_version = node[:db][:cluster].split("/").first
-pg_config = "/usr/lib/postgresql/#{db_version}/bin/pg_config"
-function_directory = "/srv/www.openstreetmap.org/rails/db/functions/#{db_version}"
-
 directory function_directory do
   owner "rails"
   group "rails"
-  mode 0o755
+  mode "755"
 end
 
 execute function_directory do
   action :nothing
-  command "make PG_CONFIG=#{pg_config} DESTDIR=#{function_directory}"
+  command "make BUNDLE=bundle#{ruby_version} PG_CONFIG=#{pg_config} DESTDIR=#{function_directory}"
   cwd "/srv/www.openstreetmap.org/rails/db/functions"
   user "rails"
   group "rails"
@@ -74,6 +77,58 @@ link "/usr/lib/postgresql/#{db_version}/lib/libpgosm.so" do
   group "root"
 end
 
+package %w[
+  cmake
+  libosmium2-dev
+  libprotozero-dev
+  libboost-filesystem-dev
+  libboost-program-options-dev
+  libbz2-dev
+  zlib1g-dev
+  libexpat1-dev
+  libyaml-cpp-dev
+  libpqxx-dev
+]
+
+git "/opt/osmdbt" do
+  action :sync
+  repository "https://github.com/openstreetmap/osmdbt.git"
+  revision "v0.2"
+  depth 1
+  user "root"
+  group "root"
+end
+
+directory "/opt/osmdbt/build-#{db_version}" do
+  owner "root"
+  group "root"
+  mode "755"
+end
+
+execute "/opt/osmdbt/CMakeLists.txt" do
+  action :nothing
+  command "cmake -DPG_CONFIG=/usr/lib/postgresql/#{db_version}/bin/pg_config .."
+  cwd "/opt/osmdbt/build-#{db_version}"
+  user "root"
+  group "root"
+  subscribes :run, "git[/opt/osmdbt]"
+end
+
+execute "/opt/osmdbt/build-#{db_version}/postgresql-plugin/Makefile" do
+  action :nothing
+  command "make"
+  cwd "/opt/osmdbt/build-#{db_version}/postgresql-plugin"
+  user "root"
+  group "root"
+  subscribes :run, "execute[/opt/osmdbt/CMakeLists.txt]"
+end
+
+link "/usr/lib/postgresql/#{db_version}/lib/osm-logical.so" do
+  to "/opt/osmdbt/build-#{db_version}/postgresql-plugin/osm-logical.so"
+  owner "root"
+  group "root"
+end
+
 package "lzop"
 
 python_package "wal-e" do
@@ -88,6 +143,6 @@ template "/usr/local/bin/openstreetmap-wal-e" do
   source "wal-e.erb"
   owner "root"
   group "postgres"
-  mode 0o750
+  mode "750"
   variables :s3_key => wal_secrets["s3_key"]
 end
index 5e51ca030478d2c2552ad796ef605a5a394f2969..f6641fd18fe85ba677d12d571c14024ac9780ab2 100644 (file)
@@ -49,6 +49,7 @@ end
 postgresql_user "planetdiff" do
   cluster node[:db][:cluster]
   password passwords["planetdiff"]
+  replication true
 end
 
 postgresql_user "backup" do
diff --git a/cookbooks/db/templates/default/backup.cron.erb b/cookbooks/db/templates/default/backup.cron.erb
deleted file mode 100644 (file)
index b7249c7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-
-MAILTO=admins@openstreetmap.org
-
-00 02 * * 1 osmbackup /usr/local/bin/backup-db
index 93f3144983c575a5e405a2a4b89f75215d6a9cc2..b4c13bd1d9f83c941e4bb31b1dc7c5215aaa91df 100644 (file)
@@ -7,4 +7,4 @@ export AWS_ACCESS_KEY_ID="AKIAIQX2LTDOBIW4CZUQ"
 export AWS_SECRET_ACCESS_KEY="<%= @s3_key %>"
 export AWS_REGION="eu-west-2"
 
-exec /usr/local/bin/wal-e "$@"
+exec /usr/local/bin/wal-e "$@" < /dev/null
index e7208b0ae63c447d064c4cd7edb44c30be7b7682..d6aa0621264b0968edfa852acf02098646fe83cf 100644 (file)
@@ -6,7 +6,7 @@
     <link rel="stylesheet" href="map.css" type="text/css" media="all" />
     <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.0/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="anonymous" />
     <script src="https://unpkg.com/leaflet@1.3.0/dist/leaflet.js" integrity="sha512-C7BBF9irt5R7hqbUm2uxtODlUVs+IsNu2UULGuZN7gM+k/mmeG4xvIEac01BtQa4YIkUpp23zZC4wIwuXaPMQA==" crossorigin="anonymous"></script>
-    <script type="text/javascript" src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
     <script type="text/javascript" src="map.js"></script>
   </head>
   <body>
index bcd716e41af04afe524558ae093085c7f479ec40..457e46dd090e4936639a5f67e5b48c6e3ad3c2ea 100644 (file)
@@ -8,10 +8,14 @@ version           "1.0.0"
 supports          "ubuntu"
 depends           "apache"
 depends           "passenger"
+depends           "chef"
+depends           "geoipupdate"
 depends           "git"
 depends           "memcached"
+depends           "munin"
 depends           "mysql"
 depends           "nodejs"
+depends           "php"
 depends           "postgresql"
 depends           "python"
 depends           "tools"
index a5729160faceb52b972d06d8ffc27dddcadb6861..e4a977f8a225487b385da6843a8f383942fb0270 100644 (file)
@@ -22,20 +22,21 @@ require "securerandom"
 
 include_recipe "apache"
 include_recipe "passenger"
+include_recipe "geoipupdate"
 include_recipe "git"
 include_recipe "memcached"
+include_recipe "munin"
 include_recipe "mysql"
 include_recipe "nodejs"
+include_recipe "php::fpm"
 include_recipe "postgresql"
 include_recipe "python"
 
 package %w[
-  php
   php-cgi
   php-cli
   php-curl
   php-db
-  php-fpm
   php-imagick
   php-mysql
   php-pear
@@ -43,14 +44,13 @@ package %w[
   php-sqlite3
   pngcrush
   pngquant
-  python
-  python-argparse
-  python-beautifulsoup
-  python-cheetah
-  python-dateutil
-  python-magic
-  python-psycopg2
-  python-gdal
+  python3
+  python3-bs4
+  python3-cheetah
+  python3-dateutil
+  python3-magic
+  python3-psycopg2
+  python3-gdal
   g++
   gcc
   make
@@ -74,7 +74,9 @@ package %w[
 
 nodejs_package "svgo"
 
-python_package "geojson"
+python_package "geojson" do
+  python_version "3"
+end
 
 apache_module "env"
 apache_module "expires"
@@ -84,38 +86,35 @@ apache_module "proxy_fcgi"
 apache_module "rewrite"
 apache_module "suexec"
 apache_module "userdir"
-apache_module "wsgi"
-
-package "apache2-suexec-pristine"
 
-service "php7.2-fpm" do
-  action [:enable, :start]
+apache_module "wsgi" do
+  package "libapache2-mod-wsgi-py3"
 end
 
-template "/etc/php/7.2/fpm/pool.d/default.conf" do
-  source "fpm-default.conf.erb"
-  owner "root"
-  group "root"
-  mode 0o644
-  notifies :reload, "service[php7.2-fpm]"
+package "apache2-suexec-pristine"
+
+php_fpm "default" do
+  pm_max_children 10
+  pm_start_servers 4
+  pm_min_spare_servers 2
+  pm_max_spare_servers 6
 end
 
-file "/etc/php/7.2/fpm/pool.d/www.conf" do
+php_fpm "www" do
   action :delete
-  notifies :reload, "service[php7.2-fpm]"
 end
 
 directory "/srv/dev.openstreetmap.org" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 template "/srv/dev.openstreetmap.org/index.html" do
   source "dev.html.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 ssl_certificate "dev.openstreetmap.org" do
@@ -133,7 +132,7 @@ template "/etc/phppgadmin/config.inc.php" do
   source "phppgadmin.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 file "/etc/apache2/conf.d/phppgadmin" do
@@ -159,15 +158,27 @@ search(:accounts, "*:*").each do |account|
 
   next unless File.directory?("#{user_home}/public_html")
 
-  port = 7000 + account["uid"].to_i
-
-  template "/etc/php/7.2/fpm/pool.d/#{name}.conf" do
-    source "fpm.conf.erb"
-    owner "root"
-    group "root"
-    mode 0o644
-    variables :user => name, :port => port
-    notifies :reload, "service[php7.2-fpm]"
+  php_fpm name do
+    user name
+    group name
+    pm_max_children 10
+    pm_start_servers 4
+    pm_min_spare_servers 2
+    pm_max_spare_servers 6
+    pm_max_requests 10000
+    request_terminate_timeout 1800
+    environment "HOSTNAME" => "$HOSTNAME",
+                "PATH" => "/usr/local/bin:/usr/bin:/bin",
+                "TMP" => "/tmp",
+                "TMPDIR" => "/tmp",
+                "TEMP" => "/tmp"
+    php_values "max_execution_time" => "300",
+               "memory_limit" => "128M",
+               "post_max_size" => "32M",
+               "upload_max_filesize" => "32M"
+    php_admin_values "sendmail_path" => "/usr/sbin/sendmail -t -i -f #{name}@errol.openstreetmap.org",
+                     "open_basedir" => "/home/#{name}/:/tmp/:/usr/share/php/"
+    php_flags "display_errors" => "on"
   end
 
   ssl_certificate "#{name}.dev.openstreetmap.org" do
@@ -178,21 +189,21 @@ search(:accounts, "*:*").each do |account|
   apache_site "#{name}.dev.openstreetmap.org" do
     template "apache.user.erb"
     directory "#{user_home}/public_html"
-    variables :user => name, :port => port
+    variables :user => name
   end
 
   template "/etc/sudoers.d/#{name}" do
     source "sudoers.user.erb"
     owner "root"
     group "root"
-    mode 0o440
+    mode "440"
     variables :user => name
   end
 end
 
-if node[:postgresql][:clusters][:"9.5/main"]
+if node[:postgresql][:clusters][:"12/main"]
   postgresql_user "apis" do
-    cluster "9.5/main"
+    cluster "12/main"
   end
 
   template "/usr/local/bin/cleanup-rails-assets" do
@@ -200,7 +211,7 @@ if node[:postgresql][:clusters][:"9.5/main"]
     source "cleanup-assets.erb"
     owner "root"
     group "root"
-    mode 0o755
+    mode "755"
   end
 
   ruby_version = node[:passenger][:ruby_version]
@@ -247,17 +258,15 @@ if node[:postgresql][:clusters][:"9.5/main"]
 
     if details[:repository]
       site_aliases = details[:aliases] || []
-      secret_key_base = details[:secret_key_base] || SecureRandom.base64(96)
-
-      node.normal[:dev][:rails][name][:secret_key_base] = secret_key_base
+      secret_key_base = persistent_token("dev", "rails", name, "secret_key_base")
 
       postgresql_database database_name do
-        cluster "9.5/main"
+        cluster "12/main"
         owner "apis"
       end
 
       postgresql_extension "#{database_name}_btree_gist" do
-        cluster "9.5/main"
+        cluster "12/main"
         database database_name
         extension "btree_gist"
       end
@@ -265,31 +274,31 @@ if node[:postgresql][:clusters][:"9.5/main"]
       directory site_directory do
         owner "apis"
         group "apis"
-        mode 0o755
+        mode "755"
       end
 
       directory log_directory do
         owner "apis"
         group "apis"
-        mode 0o755
+        mode "755"
       end
 
       directory gpx_directory do
         owner "apis"
         group "apis"
-        mode 0o755
+        mode "755"
       end
 
       directory "#{gpx_directory}/traces" do
         owner "apis"
         group "apis"
-        mode 0o755
+        mode "755"
       end
 
       directory "#{gpx_directory}/images" do
         owner "apis"
         group "apis"
-        mode 0o755
+        mode "755"
       end
 
       rails_port site_name do
@@ -299,9 +308,10 @@ if node[:postgresql][:clusters][:"9.5/main"]
         group "apis"
         repository details[:repository]
         revision details[:revision]
-        database_port node[:postgresql][:clusters][:"9.5/main"][:port]
+        database_port node[:postgresql][:clusters][:"12/main"][:port]
         database_name database_name
         database_username "apis"
+        email_from "OpenStreetMap <web@noreply.openstreetmap.org>"
         gpx_dir gpx_directory
         log_path "#{log_directory}/rails.log"
         memcache_servers ["127.0.0.1"]
@@ -314,7 +324,7 @@ if node[:postgresql][:clusters][:"9.5/main"]
         source "rails.setup.rb.erb"
         owner "apis"
         group "apis"
-        mode 0o644
+        mode "644"
         variables :site => site_name
         notifies :restart, "rails_port[#{site_name}]"
       end
@@ -368,9 +378,9 @@ if node[:postgresql][:clusters][:"9.5/main"]
           source "cgimap.environment.erb"
           owner "root"
           group "root"
-          mode 0o640
+          mode "640"
           variables :cgimap_port => cgimap_port,
-                    :database_port => node[:postgresql][:clusters][:"9.5/main"][:port],
+                    :database_port => node[:postgresql][:clusters][:"12/main"][:port],
                     :database_name => database_name,
                     :log_directory => log_directory
           notifies :restart, "service[cgimap@#{name}]"
@@ -399,7 +409,7 @@ if node[:postgresql][:clusters][:"9.5/main"]
         source "logrotate.apis.erb"
         owner "root"
         group "root"
-        mode 0o644
+        mode "644"
         variables :name => name,
                   :log_directory => log_directory,
                   :rails_directory => rails_directory
@@ -434,24 +444,22 @@ if node[:postgresql][:clusters][:"9.5/main"]
 
       postgresql_database database_name do
         action :drop
-        cluster "9.5/main"
+        cluster "12/main"
       end
-
-      node.normal[:dev][:rails].delete(name)
     end
   end
 
   directory "/srv/apis.dev.openstreetmap.org" do
     owner "apis"
     group "apis"
-    mode 0o755
+    mode "755"
   end
 
   template "/srv/apis.dev.openstreetmap.org/index.html" do
     source "apis.html.erb"
     owner "apis"
     group "apis"
-    mode 0o644
+    mode "644"
   end
 
   ssl_certificate "apis.dev.openstreetmap.org" do
@@ -474,17 +482,17 @@ end
 directory "/srv/ooc.openstreetmap.org" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 remote_directory "/srv/ooc.openstreetmap.org/html" do
   source "ooc"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   files_owner "root"
   files_group "root"
-  files_mode 0o644
+  files_mode "644"
 end
 
 ssl_certificate "ooc.openstreetmap.org" do
index ec74a54da0638f99f47468e88f2822b858e2c4c8..2965946e2ad92e8ce5d2cf7b865ae39b3fb1090d 100644 (file)
@@ -16,9 +16,9 @@
        # Remove Proxy request header to mitigate https://httpoxy.org/
        RequestHeader unset Proxy early
 
-       ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:7000/usr/share/phppgadmin
-       ProxyPassMatch ^/(.*\.phpx(/.*)?)$ fcgi://127.0.0.1:7000/usr/share/phppgadmin
-       ProxyPassMatch ^/(.*\.phpj(/.*)?)$ fcgi://127.0.0.1:7000/usr/share/phppgadmin
+       ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/run/php/default.sock|fcgi://127.0.0.1
+       ProxyPassMatch ^/(.*\.phpx(/.*)?)$ unix:/run/php/default.sock|fcgi://127.0.0.1
+       ProxyPassMatch ^/(.*\.phpj(/.*)?)$ unix:/run/php/default.sock|fcgi://127.0.0.1
 </VirtualHost>
 
 <VirtualHost *:80>
index 3c7eca7e44e864fd771e44941cddc3a90b20ae74..cf2a56613961280d80353b72ea1aa12f0b586e72 100644 (file)
 
         # Pass supported calls to cgimap
         RewriteEngine on
-        RewriteRule ^/api/0\.6/map(\.json)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
+        RewriteRule ^/api/0\.6/map(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
         RewriteCond %{REQUEST_METHOD} ^(HEAD|GET)$
-        RewriteRule ^/api/0\.6/(node|way|relation|changeset)/[0-9]+(\.json)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
-        RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/history(\.json)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
-        RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/relations(\.json)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
-        RewriteRule ^/api/0\.6/node/[0-9]+/ways(\.json)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
-        RewriteRule ^/api/0\.6/(way|relation)/[0-9]+/full(\.json)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
-        RewriteRule ^/api/0\.6/(nodes|ways|relations)(\.json)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
-        RewriteRule ^/api/0\.6/changeset/[0-9]+/(upload|download)(\.json)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
+        RewriteRule ^/api/0\.6/(node|way|relation|changeset)/[0-9]+(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
+        RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/history(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
+        RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/relations(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
+        RewriteRule ^/api/0\.6/node/[0-9]+/ways(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
+        RewriteRule ^/api/0\.6/(way|relation)/[0-9]+/full(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
+        RewriteRule ^/api/0\.6/(nodes|ways|relations)(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
+        RewriteRule ^/api/0\.6/changeset/[0-9]+/(upload|download)(\.json|\.xml)?$ fcgi://127.0.0.1:<%= @cgimap_port %>$0 [P]
 <% end -%>
 </VirtualHost>
 
index a6d4d8866402de0405897b2048174113ab6a783a..258f120d3381e8813aa88182d13b341a53926ac1 100644 (file)
@@ -1,6 +1,6 @@
 # DO NOT EDIT - This file is being maintained by Chef
 
-WSGIDaemonProcess <%= @user %>.dev.openstreetmap.org user=<%= @user %> inactivity-timeout=600
+WSGIDaemonProcess <%= @user %>.dev.openstreetmap.org user=<%= @user %> processes=2 threads=8 restart-interval=3600 inactivity-timeout=600 graceful-timeout=60 maximum-requests=2000
 
 <VirtualHost *:443>
        ServerName <%= @user %>.dev.openstreetmap.org
@@ -29,8 +29,9 @@ WSGIDaemonProcess <%= @user %>.dev.openstreetmap.org user=<%= @user %> inactivit
        RewriteCond <%= @directory %>%{REQUEST_FILENAME} -f
        RewriteRule ^/cgi-bin/(.*)$ /~<%= @user %>/cgi-bin/$1 [PT,L]
 
-       RewriteCond <%= @directory %>%{REQUEST_FILENAME} -f
-       RewriteRule ^/(.*\.ph(p|ps|p3|tml)(/.*)?)$ fcgi://127.0.0.1:<%= @port %><%= @directory %>/$1 [P]
+       <FilesMatch ".+\.ph(p|ps|p3|tml)$">
+               SetHandler "proxy:unix:/run/php/<%= @user %>.sock|fcgi://127.0.0.1"
+       </FilesMatch>
 </VirtualHost>
 
 <VirtualHost *:80>
diff --git a/cookbooks/dev/templates/default/fpm-default.conf.erb b/cookbooks/dev/templates/default/fpm-default.conf.erb
deleted file mode 100644 (file)
index fe7ee4c..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-; Start a new pool named 'default'.
-; the variable $pool can we used in any directive and will be replaced by the
-; pool name ('default' here)
-[default]
-
-; Per pool prefix
-; It only applies on the following directives:
-; - 'slowlog'
-; - 'listen' (unixsocket)
-; - 'chroot'
-; - 'chdir'
-; - 'php_values'
-; - 'php_admin_values'
-; When not set, the global prefix (or /usr) applies instead.
-; Note: This directive can also be relative to the global prefix.
-; Default Value: none
-;prefix = /path/to/pools/$pool
-
-; Unix user/group of processes
-; Note: The user is mandatory. If the group is not set, the default user's group
-;       will be used.
-user = www-data
-group = www-data
-
-; The address on which to accept FastCGI requests.
-; Valid syntaxes are:
-;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific address on
-;                            a specific port;
-;   'port'                 - to listen on a TCP socket to all addresses on a
-;                            specific port;
-;   '/path/to/unix/socket' - to listen on a unix socket.
-; Note: This value is mandatory.
-listen = 127.0.0.1:7000
-
-; Set listen(2) backlog. A value of '-1' means unlimited.
-; Default Value: 128 (-1 on FreeBSD and OpenBSD)
-;listen.backlog = -1
-
-; Set permissions for unix socket, if one is used. In Linux, read/write
-; permissions must be set in order to allow connections from a web server. Many
-; BSD-derived systems allow connections regardless of permissions. 
-; Default Values: user and group are set as the running user
-;                 mode is set to 0666
-;listen.owner = www-data
-;listen.group = www-data
-;listen.mode = 0660
-; List of ipv4 addresses of FastCGI clients which are allowed to connect.
-; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
-; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
-; must be separated by a comma. If this value is left blank, connections will be
-; accepted from any ip address.
-; Default Value: any
-;listen.allowed_clients = 127.0.0.1
-
-; Choose how the process manager will control the number of child processes.
-; Possible Values:
-;   static  - a fixed number (pm.max_children) of child processes;
-;   dynamic - the number of child processes are set dynamically based on the
-;             following directives. With this process management, there will be
-;             always at least 1 children.
-;             pm.max_children      - the maximum number of children that can
-;                                    be alive at the same time.
-;             pm.start_servers     - the number of children created on startup.
-;             pm.min_spare_servers - the minimum number of children in 'idle'
-;                                    state (waiting to process). If the number
-;                                    of 'idle' processes is less than this
-;                                    number then some children will be created.
-;             pm.max_spare_servers - the maximum number of children in 'idle'
-;                                    state (waiting to process). If the number
-;                                    of 'idle' processes is greater than this
-;                                    number then some children will be killed.
-;  ondemand - no children are created at startup. Children will be forked when
-;             new requests will connect. The following parameter are used:
-;             pm.max_children           - the maximum number of children that
-;                                         can be alive at the same time.
-;             pm.process_idle_timeout   - The number of seconds after which
-;                                         an idle process will be killed.
-; Note: This value is mandatory.
-pm = dynamic
-
-; The number of child processes to be created when pm is set to 'static' and the
-; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
-; This value sets the limit on the number of simultaneous requests that will be
-; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
-; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
-; CGI. The below defaults are based on a server without much resources. Don't
-; forget to tweak pm.* to fit your needs.
-; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
-; Note: This value is mandatory.
-pm.max_children = 10
-
-; The number of child processes created on startup.
-; Note: Used only when pm is set to 'dynamic'
-; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
-pm.start_servers = 4
-
-; The desired minimum number of idle server processes.
-; Note: Used only when pm is set to 'dynamic'
-; Note: Mandatory when pm is set to 'dynamic'
-pm.min_spare_servers = 2
-
-; The desired maximum number of idle server processes.
-; Note: Used only when pm is set to 'dynamic'
-; Note: Mandatory when pm is set to 'dynamic'
-pm.max_spare_servers = 6
-
-; The number of seconds after which an idle process will be killed.
-; Note: Used only when pm is set to 'ondemand'
-; Default Value: 10s
-;pm.process_idle_timeout = 10s;
-; The number of requests each child process should execute before respawning.
-; This can be useful to work around memory leaks in 3rd party libraries. For
-; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
-; Default Value: 0
-;pm.max_requests = 500
-
-; The URI to view the FPM status page. If this value is not set, no URI will be
-; recognized as a status page. It shows the following informations:
-;   pool                 - the name of the pool;
-;   process manager      - static, dynamic or ondemand;
-;   start time           - the date and time FPM has started;
-;   start since          - number of seconds since FPM has started;
-;   accepted conn        - the number of request accepted by the pool;
-;   listen queue         - the number of request in the queue of pending
-;                          connections (see backlog in listen(2));
-;   max listen queue     - the maximum number of requests in the queue
-;                          of pending connections since FPM has started;
-;   listen queue len     - the size of the socket queue of pending connections;
-;   idle processes       - the number of idle processes;
-;   active processes     - the number of active processes;
-;   total processes      - the number of idle + active processes;
-;   max active processes - the maximum number of active processes since FPM
-;                          has started;
-;   max children reached - number of times, the process limit has been reached,
-;                          when pm tries to start more children (works only for
-;                          pm 'dynamic' and 'ondemand');
-; Value are updated in real time.
-; Example output:
-;   pool:                 www
-;   process manager:      static
-;   start time:           01/Jul/2011:17:53:49 +0200
-;   start since:          62636
-;   accepted conn:        190460
-;   listen queue:         0
-;   max listen queue:     1
-;   listen queue len:     42
-;   idle processes:       4
-;   active processes:     11
-;   total processes:      15
-;   max active processes: 12
-;   max children reached: 0
-;
-; By default the status page output is formatted as text/plain. Passing either
-; 'html', 'xml' or 'json' in the query string will return the corresponding
-; output syntax. Example:
-;   http://www.foo.bar/status
-;   http://www.foo.bar/status?json
-;   http://www.foo.bar/status?html
-;   http://www.foo.bar/status?xml
-;
-; By default the status page only outputs short status. Passing 'full' in the
-; query string will also return status for each pool process.
-; Example: 
-;   http://www.foo.bar/status?full
-;   http://www.foo.bar/status?json&full
-;   http://www.foo.bar/status?html&full
-;   http://www.foo.bar/status?xml&full
-; The Full status returns for each process:
-;   pid                  - the PID of the process;
-;   state                - the state of the process (Idle, Running, ...);
-;   start time           - the date and time the process has started;
-;   start since          - the number of seconds since the process has started;
-;   requests             - the number of requests the process has served;
-;   request duration     - the duration in µs of the requests;
-;   request method       - the request method (GET, POST, ...);
-;   request URI          - the request URI with the query string;
-;   content length       - the content length of the request (only with POST);
-;   user                 - the user (PHP_AUTH_USER) (or '-' if not set);
-;   script               - the main script called (or '-' if not set);
-;   last request cpu     - the %cpu the last request consumed
-;                          it's always 0 if the process is not in Idle state
-;                          because CPU calculation is done when the request
-;                          processing has terminated;
-;   last request memory  - the max amount of memory the last request consumed
-;                          it's always 0 if the process is not in Idle state
-;                          because memory calculation is done when the request
-;                          processing has terminated;
-; If the process is in Idle state, then informations are related to the
-; last request the process has served. Otherwise informations are related to
-; the current request being served.
-; Example output:
-;   ************************
-;   pid:                  31330
-;   state:                Running
-;   start time:           01/Jul/2011:17:53:49 +0200
-;   start since:          63087
-;   requests:             12808
-;   request duration:     1250261
-;   request method:       GET
-;   request URI:          /test_mem.php?N=10000
-;   content length:       0
-;   user:                 -
-;   script:               /home/fat/web/docs/php/test_mem.php
-;   last request cpu:     0.00
-;   last request memory:  0
-;
-; Note: There is a real-time FPM status monitoring sample web page available
-;       It's available in: ${prefix}/share/fpm/status.html
-;
-; Note: The value must start with a leading slash (/). The value can be
-;       anything, but it may not be a good idea to use the .php extension or it
-;       may conflict with a real PHP file.
-; Default Value: not set 
-;pm.status_path = /status
-; The ping URI to call the monitoring page of FPM. If this value is not set, no
-; URI will be recognized as a ping page. This could be used to test from outside
-; that FPM is alive and responding, or to
-; - create a graph of FPM availability (rrd or such);
-; - remove a server from a group if it is not responding (load balancing);
-; - trigger alerts for the operating team (24/7).
-; Note: The value must start with a leading slash (/). The value can be
-;       anything, but it may not be a good idea to use the .php extension or it
-;       may conflict with a real PHP file.
-; Default Value: not set
-;ping.path = /ping
-
-; This directive may be used to customize the response of a ping request. The
-; response is formatted as text/plain with a 200 response code.
-; Default Value: pong
-;ping.response = pong
-
-; The access log file
-; Default: not set
-;access.log = log/$pool.access.log
-
-; The access log format.
-; The following syntax is allowed
-;  %%: the '%' character
-;  %C: %CPU used by the request
-;      it can accept the following format:
-;      - %{user}C for user CPU only
-;      - %{system}C for system CPU only
-;      - %{total}C  for user + system CPU (default)
-;  %d: time taken to serve the request
-;      it can accept the following format:
-;      - %{seconds}d (default)
-;      - %{miliseconds}d
-;      - %{mili}d
-;      - %{microseconds}d
-;      - %{micro}d
-;  %e: an environment variable (same as $_ENV or $_SERVER)
-;      it must be associated with embraces to specify the name of the env
-;      variable. Some exemples:
-;      - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e
-;      - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e
-;  %f: script filename
-;  %l: content-length of the request (for POST request only)
-;  %m: request method
-;  %M: peak of memory allocated by PHP
-;      it can accept the following format:
-;      - %{bytes}M (default)
-;      - %{kilobytes}M
-;      - %{kilo}M
-;      - %{megabytes}M
-;      - %{mega}M
-;  %n: pool name
-;  %o: ouput header
-;      it must be associated with embraces to specify the name of the header:
-;      - %{Content-Type}o
-;      - %{X-Powered-By}o
-;      - %{Transfert-Encoding}o
-;      - ....
-;  %p: PID of the child that serviced the request
-;  %P: PID of the parent of the child that serviced the request
-;  %q: the query string 
-;  %Q: the '?' character if query string exists
-;  %r: the request URI (without the query string, see %q and %Q)
-;  %R: remote IP address
-;  %s: status (response code)
-;  %t: server time the request was received
-;      it can accept a strftime(3) format:
-;      %d/%b/%Y:%H:%M:%S %z (default)
-;  %T: time the log has been written (the request has finished)
-;      it can accept a strftime(3) format:
-;      %d/%b/%Y:%H:%M:%S %z (default)
-;  %u: remote user
-;
-; Default: "%R - %u %t \"%m %r\" %s"
-;access.format = %R - %u %t "%m %r%Q%q" %s %f %{mili}d %{kilo}M %C%%
-; The log file for slow requests
-; Default Value: not set
-; Note: slowlog is mandatory if request_slowlog_timeout is set
-;slowlog = log/$pool.log.slow
-; The timeout for serving a single request after which a PHP backtrace will be
-; dumped to the 'slowlog' file. A value of '0s' means 'off'.
-; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
-; Default Value: 0
-;request_slowlog_timeout = 0
-; The timeout for serving a single request after which the worker process will
-; be killed. This option should be used when the 'max_execution_time' ini option
-; does not stop script execution for some reason. A value of '0' means 'off'.
-; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
-; Default Value: 0
-;request_terminate_timeout = 0
-; Set open file descriptor rlimit.
-; Default Value: system defined value
-;rlimit_files = 1024
-; Set max core size rlimit.
-; Possible Values: 'unlimited' or an integer greater or equal to 0
-; Default Value: system defined value
-;rlimit_core = 0
-; Chroot to this directory at the start. This value must be defined as an
-; absolute path. When this value is not set, chroot is not used.
-; Note: you can prefix with '$prefix' to chroot to the pool prefix or one
-; of its subdirectories. If the pool prefix is not set, the global prefix
-; will be used instead.
-; Note: chrooting is a great security feature and should be used whenever 
-;       possible. However, all PHP paths will be relative to the chroot
-;       (error_log, sessions.save_path, ...).
-; Default Value: not set
-;chroot = 
-; Chdir to this directory at the start.
-; Note: relative path can be used.
-; Default Value: current directory or / when chroot
-chdir = /
-; Redirect worker stdout and stderr into main error log. If not set, stdout and
-; stderr will be redirected to /dev/null according to FastCGI specs.
-; Note: on highloaded environement, this can cause some delay in the page
-; process time (several ms).
-; Default Value: no
-;catch_workers_output = yes
-
-; Limits the extensions of the main script FPM will allow to parse. This can
-; prevent configuration mistakes on the web server side. You should only limit
-; FPM to .php extensions to prevent malicious users to use other extensions to
-; exectute php code.
-; Note: set an empty value to allow all extensions.
-; Default Value: .php
-;security.limit_extensions = .php .php3 .php4 .php5
-; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
-; the current environment.
-; Default Value: clean env
-;env[HOSTNAME] = $HOSTNAME
-;env[PATH] = /usr/local/bin:/usr/bin:/bin
-;env[TMP] = /tmp
-;env[TMPDIR] = /tmp
-;env[TEMP] = /tmp
-
-; Additional php.ini defines, specific to this pool of workers. These settings
-; overwrite the values previously defined in the php.ini. The directives are the
-; same as the PHP SAPI:
-;   php_value/php_flag             - you can set classic ini defines which can
-;                                    be overwritten from PHP call 'ini_set'. 
-;   php_admin_value/php_admin_flag - these directives won't be overwritten by
-;                                     PHP call 'ini_set'
-; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no.
-
-; Defining 'extension' will load the corresponding shared extension from
-; extension_dir. Defining 'disable_functions' or 'disable_classes' will not
-; overwrite previously defined php.ini values, but will append the new value
-; instead.
-
-; Note: path INI options can be relative and will be expanded with the prefix
-; (pool, global or /usr)
-
-; Default Value: nothing is defined by default except the values in php.ini and
-;                specified at startup with the -d argument
-;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com
-;php_flag[display_errors] = off
-;php_admin_value[error_log] = /var/log/fpm-php.www.log
-;php_admin_flag[log_errors] = on
-;php_admin_value[memory_limit] = 32M
diff --git a/cookbooks/dev/templates/default/fpm.conf.erb b/cookbooks/dev/templates/default/fpm.conf.erb
deleted file mode 100644 (file)
index 523d8ca..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-; DO NOT EDIT - This file is being maintained by Chef
-
-[<%= @user %>]
-listen = 127.0.0.1:<%= @port %>
-listen.backlog = 256
-
-user = <%= @user %>
-group = <%= @user %>
-
-pm = dynamic
-pm.max_children = 10
-pm.start_servers = 4
-pm.min_spare_servers = 2
-pm.max_spare_servers = 6
-pm.max_requests = 10000
-
-request_terminate_timeout = 1800
-
-;pm.status_path = /status
-;ping.path = /ping
-;ping.response = pong
-;request_terminate_timeout = 0
-;request_slowlog_timeout = 0
-;slowlog = /var/log/php5-fpm.log.slow
-;rlimit_files = 1024
-;rlimit_core = 0
-;chroot = 
-;chdir = /var/www
-;catch_workers_output = yes
-env[HOSTNAME] = $HOSTNAME
-env[PATH] = /usr/local/bin:/usr/bin:/bin
-env[TMP] = /tmp
-env[TMPDIR] = /tmp
-env[TEMP] = /tmp
-
-php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f <%= @user %>@errol.openstreetmap.org
-php_admin_value[open_basedir] = /home/<%= @user %>/:/tmp/:/usr/share/php/
-php_flag[display_errors] = on
-;php_admin_value[error_log] = /var/log/fpm-php.www.log
-;php_admin_flag[log_errors] = on
-php_value[max_execution_time] = 300
-php_value[memory_limit] = 128M
-php_value[post_max_size] = 32M
-php_value[upload_max_filesize] = 32M
-
index 0b8ba5a514d02d7670ff903e0c66f779b1b4334d..8572dd232755abde2ca33c1187deb69d98b14f6a 100644 (file)
 cookbook_file "/usr/local/bin/fixeep-82574_83.sh" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 execute "udevadm-trigger" do
   action :nothing
-  command "/sbin/udevadm trigger --action=add"
+  command "/bin/udevadm trigger --action=add"
 end
 
 template "/etc/udev/rules.d/99-chef.rules" do
   source "udev.rules.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :run, "execute[udevadm-trigger]"
 end
index bc6f67eb4aa2215a3a925b438c0a7ae2014106b9..2c687566ceae531e237a6d4c5a76a9baa13fbcfb 100644 (file)
@@ -1,10 +1,16 @@
 # DO NOT EDIT - This file is being maintained by Chef
 
 # HP Smart Array configuration
-ACTION=="add", SUBSYSTEM=="block", ENV{ID_VENDOR}=="HP", ENV{ID_MODEL}=="LOGICAL_VOLUME", ATTR{queue/scheduler}="noop"
-ACTION=="add", SUBSYSTEM=="block", ENV{ID_VENDOR}=="HP", ENV{ID_MODEL}=="LOGICAL_VOLUME", ATTR{queue/nr_requests}="512"
-ACTION=="add", SUBSYSTEM=="block", ENV{ID_VENDOR}=="HP", ENV{ID_MODEL}=="LOGICAL_VOLUME", ATTR{queue/read_ahead_kb}="4096"
-ACTION=="add", SUBSYSTEM=="block", ENV{ID_VENDOR}=="HP", ENV{ID_MODEL}=="LOGICAL_VOLUME", ATTR{queue/rq_affinity}="2"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_VENDOR}=="HP", ENV{ID_MODEL}=="LOGICAL_VOLUME", ATTR{queue/scheduler}="noop"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_VENDOR}=="HP", ENV{ID_MODEL}=="LOGICAL_VOLUME", ATTR{queue/nr_requests}="512"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_VENDOR}=="HP", ENV{ID_MODEL}=="LOGICAL_VOLUME", ATTR{queue/read_ahead_kb}="4096"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_VENDOR}=="HP", ENV{ID_MODEL}=="LOGICAL_VOLUME", ATTR{queue/rq_affinity}="2"
+
+# Dell PERC H710 tune
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_VENDOR}=="DELL", ENV{ID_MODEL}=="PERC_H710", ATTR{queue/read_ahead_kb}="4096"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_VENDOR}=="DELL", ENV{ID_MODEL}=="PERC_H710", ATTR{queue/scheduler}="deadline"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_VENDOR}=="DELL", ENV{ID_MODEL}=="PERC_H710", ATTR{queue/nr_requests}="512"
+
 <% node[:devices].each do |name,device| -%>
 
 # <%= device[:comment] %>
@@ -26,14 +32,66 @@ ACTION=="add", SUBSYSTEM=="block", ENV{ID_BUS}=="<%= device[:bus] %>", ENV{ID_SE
 <% end -%>
 <% end -%>
 
+# Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x10ec", ATTRS{device}=="0x8168", RUN+="/sbin/ethtool -K $name tso off gso off"
+
+# Ethernet controller: Mellanox Technologies MT27710 Family [ConnectX-4 Lx]
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x15b3", ATTRS{device}=="0x1015", RUN+="/sbin/ethtool -G $name rx 8192 tx 8192"
+
+# Ethernet controller: Broadcom Inc. and subsidiaries NetXtreme II BCM5709 Gigabit Ethernet
+# Hewlett-Packard Company NC382i Integrated Multi-port PCI Express Gigabit Server Adapter
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x14e4", ATTRS{device}=="0x1639", RUN+="/sbin/ethtool -G $name rx 2040"
+# Ethernet controller: Broadcom Inc. and subsidiaries NetXtreme II BCM5708 Gigabit Ethernet
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x14e4", ATTRS{device}=="0x164c", RUN+="/sbin/ethtool -G $name rx 2040"
+# Ethernet controller: Broadcom Inc. and subsidiaries NetXtreme BCM5719 Gigabit Ethernet PCIe
+# Hewlett-Packard Company Ethernet 1Gb 4-port 331i Adapter
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x14e4", ATTRS{device}=="0x1657", RUN+="/sbin/ethtool -G $name rx 2047"
+# Ethernet controller: Broadcom Inc. and subsidiaries NetXtreme BCM5721 Gigabit Ethernet PCI Express
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x14e4", ATTRS{device}=="0x1659", RUN+="/sbin/ethtool -G $name rx 511"
+# Ethernet controller: Broadcom Inc. and subsidiaries NetXtreme BCM5720 2-port Gigabit Ethernet PCIe
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x14e4", ATTRS{device}=="0x165f", RUN+="/sbin/ethtool -G $name rx 2047"
+
+# Ethernet controller: Intel Corporation 82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications)
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x105e", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Ethernet controller: Intel Corporation 80003ES2LAN Gigabit Ethernet Controller (Copper)
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1096", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Ethernet controller: Intel Corporation 82575EB Gigabit Network Connection
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x10a7", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
 # Disable scatter-gather offload for HP NC362i network controllers
 SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x10c9", ATTRS{subsystem_vendor}=="0x103c", ATTRS{subsystem_device}=="0x323f", RUN+="/sbin/ethtool -K $name gso off tso off sg off gro off"
-
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x10c9", ATTRS{subsystem_vendor}=="0x103c", ATTRS{subsystem_device}=="0x323f", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Ethernet controller: Intel Corporation 82574L Gigabit Network Connection
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x10d3", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
 # Fix Power Saving Bug on Intel 82574L and Intel 82583 network controllers
 SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x10d3", RUN+="/usr/local/bin/fixeep-82574_83.sh $name"
 SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x10f6", RUN+="/usr/local/bin/fixeep-82574_83.sh $name"
 SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x150c", RUN+="/usr/local/bin/fixeep-82574_83.sh $name"
 
+# Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x10fb", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Ethernet controller: Intel Corporation 82580 Gigabit Network Connection
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x150e", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Ethernet controller: Intel Corporation I350 Gigabit Network Connection
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1521", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1528", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Ethernet controller: Intel Corporation I210 Gigabit Network Connection
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1533", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Ethernet controller: Intel Corporation I211 Gigabit Network Connection
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1539", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev 03)
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x157b", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Ethernet controller: Intel Corporation Ethernet Controller 10G X550T
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1563", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Ethernet controller: Intel Corporation Ethernet Controller X710 for 10GBASE-T
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1586", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Ethernet controller: Intel Corporation Ethernet Controller X710 for 10GBASE-T
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x15ff", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Ethernet controller: Intel Corporation Ethernet Connection I354 (rev 03)
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1f41", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+# Ethernet controller: Intel Corporation Ethernet Connection X722 for 10GBASE-T
+SUBSYSTEM=="net", ACTION=="add", ATTRS{vendor}=="0x8086", ATTRS{device}=="0x37d2", RUN+="/sbin/ethtool -G $name rx 4096 tx 4096"
+
 # Workaround unreliable Western Digital WD RE3/RE4 disks (ATA only)
 # Set sufficent Linux subsystem timeout and fix severe NCQ performance issue
 ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="WDC_WD5002ABYS-02B1B0", ATTR{device/timeout}="90", ATTR{device/queue_depth}="1", ATTR{queue/nr_requests}="256"
@@ -53,8 +111,47 @@ ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV
 ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="HGST_HTS725050A7E630", RUN+="/usr/sbin/smartctl -q errorsonly -l scterc,100,100 $env{DEVNAME}"
 ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="HGST_HTE721010A9E630", RUN+="/usr/sbin/smartctl -q errorsonly -l scterc,100,100 $env{DEVNAME}"
 
+# Add SSD optimisation
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="OCZ-VERTEX3", ATTR{queue/read_ahead_kb}="4096"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="OCZ-VERTEX3", ATTR{queue/scheduler}="noop"
+
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="Samsung_SSD_840_PRO_*", ATTR{queue/read_ahead_kb}="4096"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="Samsung_SSD_840_PRO_*", ATTR{queue/scheduler}="noop"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="Samsung_SSD_840_PRO_*", ATTR{queue/read_ahead_kb}="256"
+
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="Samsung_SSD_850_PRO_*", ATTR{queue/read_ahead_kb}="4096"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="Samsung_SSD_850_PRO_*", ATTR{queue/scheduler}="noop"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="Samsung_SSD_850_PRO_*", ATTR{queue/read_ahead_kb}="256"
+
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="Samsung_SSD_860_PRO_*", ATTR{queue/read_ahead_kb}="4096"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="Samsung_SSD_860_PRO_*", ATTR{queue/scheduler}="noop"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="Samsung_SSD_860_PRO_*", ATTR{queue/read_ahead_kb}="256"
+
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="ST240FN0021", ATTR{queue/read_ahead_kb}="4096"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="ST240FN0021", ATTR{queue/scheduler}="noop"
+
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="SuperMicro_SSD", ATTR{queue/read_ahead_kb}="4096"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="SuperMicro_SSD", ATTR{queue/scheduler}="noop"
+
+# Delete failed disk in cmok
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_BUS}=="ata", ENV{ID_MODEL}=="ST_M13FQBL", ENV{ID_SERIAL}=="ST_M13FQBL_QNR_BFW", ATTR{device/delete}="1"
+
 # Enable request merging for NVME devices
 ACTION=="add", SUBSYSTEM=="block", DRIVERS=="nvme", ATTR{queue/nomerges}="1"
 
+# VMware Virtual disk configuration
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_VENDOR}=="VMware", ENV{ID_MODEL}=="Virtual_disk", ATTR{queue/read_ahead_kb}="4096"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_VENDOR}=="VMware", ENV{ID_MODEL}=="Virtual_disk", ATTR{queue/scheduler}="noop"
+
 # Increase readahead on virtio block devices
-ACTION=="add", SUBSYSTEM=="block", DRIVERS=="virtio_blk", ATTR{queue/read_ahead_kb}="512"
+ACTION=="add", SUBSYSTEM=="block", DRIVERS=="virtio_blk", ATTR{queue/read_ahead_kb}="4096"
+# Note virtio sets scheduler to none automatically
+
+# QEMU Disk IO tune
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_MODEL}=="QEMU_HARDDISK", ATTR{queue/read_ahead_kb}="4096"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_MODEL}=="QEMU_HARDDISK", ATTR{queue/scheduler}="noop"
+# Vendor is sometimes missing
+
+# Increase default MD raid5/raid6 strip cache + group_thread_cnt
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{MD_LEVEL}=="raid5", ATTR{md/stripe_cache_size}="8192", ATTR{md/group_thread_cnt}="4"
+ACTION=="add", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{MD_LEVEL}=="raid6", ATTR{md/stripe_cache_size}="8192", ATTR{md/group_thread_cnt}="4"
index cc693c7df23b3e6e9498319a95bc9b0a5f5a8049..2e239b15745d5a275aa2ecb83885ee8069e1c055 100644 (file)
@@ -7,3 +7,4 @@ description       "Configures dhcpd"
 version           "1.0.0"
 supports          "ubuntu"
 depends           "networking"
+depends           "ntp"
index 18343a67d1afea65f01c4c13090611d41e76affc..a8f0dd6f7a52a9affb1119584a1669c16988bbbf 100644 (file)
@@ -27,7 +27,7 @@ template "/etc/dhcp/dhcpd.conf" do
   source "dhcpd.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   variables :domain => domain
 end
 
index 78397dff73c33430733a80a2152fcaa49345b823..af2496deccbc36ce8bf3d67d8490e876641de9fd 100644 (file)
@@ -129,6 +129,18 @@ host sarel.oob.openstreetmap.org {
   fixed-address sarel.oob.openstreetmap.org;
 }
 
+host snap-01.oob.openstreetmap.org {
+  hardware ethernet 3c:ec:ef:17:a6:72;
+  server-name "snap-01.oob.openstreetmap.org";
+  fixed-address snap-01.oob.openstreetmap.org;
+}
+
+host snap-02.oob.openstreetmap.org {
+  hardware ethernet 3c:ec:ef:17:a5:37;
+  server-name "snap-02.oob.openstreetmap.org";
+  fixed-address snap-02.oob.openstreetmap.org;
+}
+
 host smaug.oob.openstreetmap.org {
   hardware ethernet 00:30:48:9d:57:ff;
   server-name "smaug.oob.openstreetmap.org";
index 4b283d3b30cd9afaae840ab464e3ff7c1f79b592..47e1afb064388f2c6858df365b942018e7fbd869 100644 (file)
@@ -10,7 +10,10 @@ function process_data ($values) {
         $email_body = 'OpenStreetMap - Claim of Copyright Infringement form:'."\n\n";
         $email_body .= 'Automated Email - Form Posted.'."\n\n";
         $email_body .= print_r($values, true);
-        mail('dmca@osmfoundation.org','OSM Claim of Copyright Infringement', $email_body, 'From: OSMF Copyright Form <dmca@osmfoundation.org>', '-fdmca@osmfoundation.org');
+        $reply_address = $values['name_first'].' '.$values['name_last'].' <'.$values['email'].'>';
+        $email_body .= 'Formatted address: '.$reply_address."\n\n";
+        $email_header = 'From: OSMF Copyright Form <dmca@osmfoundation.org>' . "\r\n" . 'Content-Type: text/plain; charset="utf-8"';
+        mail('dmca@osmfoundation.org','OSM Claim of Copyright Infringement', $email_body, $email_header, '-fdmca@osmfoundation.org');
 }
 ?>
 <!DOCTYPE html>
@@ -37,7 +40,8 @@ $form->addElement('static', null, '<p>To file a copyright infringement notificat
 <li>A statement that the complaining party has a good faith belief that use of the material in the manner complained of is not authorized by the copyright owner, its agent, or the law.
 <li>A statement that the information in the notification is accurate and, under penalty of perjury, that the complaining party is authorized to act on behalf of the owner of an exclusive right that is allegedly infringed.
 </ul><p>To expedite our ability to process your request, such written notice should be sent to our designated agent via our online copyright complaint form below.</p>
-<p>This form is only for cases where you believe that material on OpenStreetMap\'s websites or in its geodata database infringes your copyright or that of your clients. For example, you claim someone has copied material from a map belonging to you. If you have come here for another reason, <a href="https://wiki.osmfoundation.org/wiki/Licence_and_Legal_FAQ/Takedown_procedure/When_To_Use_The_Form">Go here</a>.</p>');
+<p>This form is only for cases where you believe that material on OpenStreetMap\'s websites or in its geodata database infringes your copyright or that of your clients. For example, you claim someone has copied material from a map belonging to you.</p>
+<p>If you have come here for reporting map inaccuracies, privacy issues or another reason, <a href="https://wiki.osmfoundation.org/wiki/Licence_and_Legal_FAQ/Takedown_procedure/When_To_Use_The_Form">Read here</a>.</p>');
 
 $form->addElement('text', 'url',                'URL of Allegedly Infringing Material', array('size' => 50, 'maxlength' => 255));
 $form->addRule('url', 'Please enter URL of Allegedly Infringing Material', 'required', null, 'client');
index 6b12e982253a2d269ed003622ad9463e13f842ec..9876562950f7c88f5a86e600a6710b9e2ebea945 100644 (file)
@@ -7,3 +7,4 @@ description       "Configure DMCA form"
 version           "1.0.0"
 supports          "ubuntu"
 depends           "apache"
+depends           "php"
index 652ae8cb86dc4d8db6a9295be2b71f3acb5fff7f..f7f9cfadbc59639090115c52c211dc4e8fea663d 100644 (file)
 #
 
 include_recipe "apache"
+include_recipe "php::fpm"
 
-apache_module "php7.2"
+apache_module "proxy"
+apache_module "proxy_fcgi"
 
 directory "/srv/dmca.openstreetmap.org" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 remote_directory "/srv/dmca.openstreetmap.org/html" do
   source "html"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   files_owner "root"
   files_group "root"
-  files_mode 0o644
+  files_mode "644"
 end
 
 ssl_certificate "dmca.openstreetmap.org" do
@@ -42,6 +44,12 @@ ssl_certificate "dmca.openstreetmap.org" do
   notifies :reload, "service[apache2]"
 end
 
+php_fpm "dmca.openstreetmap.org" do
+  php_admin_values "open_basedir" => "/srv/dmca.openstreetmap.org/html/:/usr/share/php/:/tmp/",
+                   "disable_functions" => "exec,shell_exec,system,passthru,popen,proc_open"
+  prometheus_port 11201
+end
+
 apache_site "dmca.openstreetmap.org" do
   template "apache.erb"
   directory "/srv/dmca.openstreetmap.org"
index bf53e2d2e41b4449a0e198ab6a3f8476a61a1911..672a1be3e7d9903d7cce88779e9935c54d446e91 100644 (file)
@@ -51,4 +51,8 @@
 
 <Directory <%= @directory %>/html>
   Require all granted
+
+  <FilesMatch ".+\.ph(ar|p|tml)$">
+    SetHandler "proxy:unix:/run/php/<%= @name %>.sock|fcgi://127.0.0.1"
+  </FilesMatch>
 </Directory>
diff --git a/cookbooks/dns/attributes/default.rb b/cookbooks/dns/attributes/default.rb
new file mode 100644 (file)
index 0000000..5bc8153
--- /dev/null
@@ -0,0 +1,3 @@
+default[:dns][:repository] = "/var/lib/git/public/dns.git"
+
+default[:accounts][:users][:git][:status] = :role
index ee177a46b81c26c660eb0eba8e17c3145c55f7be..fb112068119ccb5be9e87dd923fc7e5f45cf04f8 100644 (file)
@@ -6,5 +6,6 @@ description       "Configure DNS management"
 
 version           "1.0.0"
 supports          "ubuntu"
-depends           "git"
+depends           "accounts"
 depends           "apache"
+depends           "git"
index 1896e99b82e99d0049e2ad6d8a2384f2111f222a..eaeaf562373572bc30b20a9a000b951ae6964532 100644 (file)
@@ -17,8 +17,9 @@
 # limitations under the License.
 #
 
-include_recipe "git"
+include_recipe "accounts"
 include_recipe "apache"
+include_recipe "git"
 
 geoservers = search(:node, "roles:geodns").collect(&:name).sort
 
@@ -29,27 +30,37 @@ package %w[
   parallel
   rsync
   perl
+  libdigest-sha-perl
+  libjson-xs-perl
+  libwww-perl
   libxml-treebuilder-perl
   libxml-writer-perl
-  libyaml-perl
-  libwww-perl
-  libjson-xs-perl
+  libyaml-libyaml-perl
+  lockfile-progs
 ]
 
+remote_file "/usr/local/bin/dnscontrol" do
+  action :create
+  source "https://github.com/StackExchange/dnscontrol/releases/download/v3.5.0/dnscontrol-Linux"
+  owner "root"
+  group "root"
+  mode "755"
+end
+
 directory "/srv/dns.openstreetmap.org" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 remote_directory "/srv/dns.openstreetmap.org/html" do
   source "html"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   files_owner "root"
   files_group "root"
-  files_mode 0o644
+  files_mode "644"
 end
 
 zones = []
@@ -61,7 +72,7 @@ Dir.glob("/var/lib/dns/json/*.json").each do |kmlfile|
     source "zone.html.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables :zone => zone
   end
 
@@ -72,7 +83,7 @@ template "/srv/dns.openstreetmap.org/html/index.html" do
   source "index.html.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   variables :zones => zones
 end
 
@@ -91,7 +102,7 @@ template "/usr/local/bin/dns-update" do
   source "dns-update.erb"
   owner "root"
   group "git"
-  mode 0o750
+  mode "750"
   variables :passwords => passwords, :geoservers => geoservers
 end
 
@@ -105,28 +116,37 @@ end
 directory "/var/lib/dns" do
   owner "git"
   group "git"
-  mode 0o2775
+  mode "2775"
   notifies :run, "execute[dns-update]"
 end
 
+template "/var/lib/dns/creds.json" do
+  source "creds.json.erb"
+  owner "git"
+  group "git"
+  mode "440"
+  variables :passwords => passwords
+end
+
 cookbook_file "#{node[:dns][:repository]}/hooks/post-receive" do
   source "post-receive"
   owner "git"
   group "git"
-  mode 0o750
+  mode "750"
+  only_if { ::Dir.exist?("#{node[:dns][:repository]}/hooks") }
 end
 
 template "/usr/local/bin/dns-check" do
   source "dns-check.erb"
   owner "root"
   group "git"
-  mode 0o750
+  mode "750"
   variables :passwords => passwords, :geoservers => geoservers
 end
 
-template "/etc/cron.d/dns" do
-  source "cron.erb"
-  owner "root"
-  group "root"
-  mode 0o644
+cron_d "dns" do
+  minute "*/3"
+  user "git"
+  command "/usr/local/bin/dns-check"
+  mailto "admins@openstreetmap.org"
 end
diff --git a/cookbooks/dns/templates/default/creds.json.erb b/cookbooks/dns/templates/default/creds.json.erb
new file mode 100644 (file)
index 0000000..980c0fb
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "gandi_v5": {
+    "apikey": "<%= @passwords["gandi"] %>",
+    "sharing_id": "7028b616-ba65-11e7-8343-00163ec31f40"
+  },
+  "cloudflare": {
+    "accountid": "049c95aba02c95fc1e78a9d255282e0f",
+    "accountname": "OpenStreetMap",
+    "apitoken": "<%= @passwords["cloudflare"] %>"
+  }
+}
index ca38dddc83f98bf565333ba182b6cc38a34cbab6..09f061b67db9c420872c7cac08093edfe1cd97f8 100755 (executable)
@@ -1,10 +1,12 @@
 #!/bin/sh
 
-export RSYNC_PASSWORD="<%= @passwords["rsync"] %>"
 export GEODNS_SERVERS="<%= @geoservers.join(" ") %>"
-export PINGDOM_USERNAME="pingdom@openstreetmap.org"
-export PINGDOM_PASSWORD="<%= @passwords["pingdom"] %>"
 export STATUSCAKE_USERNAME="OpenStreetMap"
 export STATUSCAKE_APIKEY="<%= @passwords["statuscake"] %>"
+export PATH=/usr/local/bin:$PATH
 
-make --quiet --jobs --directory=/var/lib/dns --assume-new=lib/countries.xml update > /dev/null
+lockfile-create --use-pid /var/lib/dns/update || exit 1
+
+make --quiet --jobs --directory=/var/lib/dns update_primary > /dev/null
+
+lockfile-remove /var/lib/dns/update
index 401c5c74f05bbac9e1020f334d8db6f91e4e8fa3..5353d69d42daa35841e7f0c3deb7a516af662250 100755 (executable)
@@ -4,15 +4,15 @@
 
 umask 0002
 
-export RSYNC_PASSWORD="<%= @passwords["rsync"] %>"
 export GEODNS_SERVERS="<%= @geoservers.join(" ") %>"
-export PINGDOM_USERNAME="pingdom@openstreetmap.org"
-export PINGDOM_PASSWORD="<%= @passwords["pingdom"] %>"
 export STATUSCAKE_USERNAME="OpenStreetMap"
 export STATUSCAKE_APIKEY="<%= @passwords["statuscake"] %>"
+export PATH=/usr/local/bin:$PATH
 
 cd /var/lib/dns
 
+lockfile-create --use-pid update || exit 1
+
 if [ ! -d .git ]
 then
   git clone /var/lib/git/public/dns.git /var/lib/dns
@@ -21,3 +21,5 @@ fi
 git pull -q
 
 make --jobs update
+
+lockfile-remove update
index 3bf01af60011dde3fdcdb2a87720eb8552be7a0f..fb34d94bd3bdaee8504647e4d76a90f8ee610b10 100644 (file)
@@ -6,7 +6,7 @@
     <link rel="stylesheet" href="dns.css" type="text/css" media="all" />
     <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.0/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="anonymous" />
     <script src="https://unpkg.com/leaflet@1.3.0/dist/leaflet.js" integrity="sha512-C7BBF9irt5R7hqbUm2uxtODlUVs+IsNu2UULGuZN7gM+k/mmeG4xvIEac01BtQa4YIkUpp23zZC4wIwuXaPMQA==" crossorigin="anonymous"></script>
-    <script type="text/javascript" src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
     <script type="text/javascript" src="dns.js"></script>
   </head>
   <body onload="createMap('map', 'json/<%= @zone %>.json')">
diff --git a/cookbooks/docker/attributes/default.rb b/cookbooks/docker/attributes/default.rb
new file mode 100644 (file)
index 0000000..f71e326
--- /dev/null
@@ -0,0 +1,2 @@
+# Add the docker APT source
+default[:apt][:sources] = node[:apt][:sources] | ["docker"]
similarity index 61%
rename from cookbooks/openvpn/metadata.rb
rename to cookbooks/docker/metadata.rb
index 15bee3b880aebfa37e01bb8cf1da30ff5c9dc338..110cc32020e69ef10fb2927dfcb21b89a6d5f5b3 100644 (file)
@@ -1,8 +1,9 @@
-name              "openvpn"
+name              "docker"
 maintainer        "OpenStreetMap Administrators"
 maintainer_email  "admins@openstreetmap.org"
 license           "Apache-2.0"
-description       "Installs and configures OpenVPN"
+description       "Installs and configures the docker daemon"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "apt"
diff --git a/cookbooks/docker/recipes/default.rb b/cookbooks/docker/recipes/default.rb
new file mode 100644 (file)
index 0000000..23891f1
--- /dev/null
@@ -0,0 +1,45 @@
+#
+# Cookbook:: docker
+# Recipe:: default
+#
+# Copyright:: 2020, OpenStreetMap Foundation
+#
+# 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
+#
+#     https://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.
+#
+
+include_recipe "apt"
+
+package %w[
+  docker-ce
+  docker-ce-cli
+  containerd.io
+]
+
+directory "/etc/docker" do
+  owner "root"
+  group "root"
+  mode "755"
+end
+
+template "/etc/docker/daemon.json" do
+  source "daemon.json.erb"
+  owner "root"
+  group "root"
+  mode "644"
+end
+
+service "docker" do
+  action [:enable, :start]
+  subscribes :restart, "template[/etc/docker/daemon.json]"
+  not_if { ENV["TEST_KITCHEN"] }
+end
diff --git a/cookbooks/docker/templates/default/daemon.json.erb b/cookbooks/docker/templates/default/daemon.json.erb
new file mode 100644 (file)
index 0000000..5d18abc
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "exec-opts": ["native.cgroupdriver=systemd"],
+  "log-driver": "json-file",
+  "log-opts": {
+    "max-size": "100m"
+  },
+  "storage-driver": "overlay2"
+}
diff --git a/cookbooks/donate/attributes/default.rb b/cookbooks/donate/attributes/default.rb
new file mode 100644 (file)
index 0000000..c6c3785
--- /dev/null
@@ -0,0 +1,2 @@
+# Enable the "donate" role
+default[:accounts][:users][:donate][:status] = :role
index 0882bddf8cc9522c60ae639218b558ca0598f181..4c4649b1a065a93c72365c35e75aab9fe109b70f 100644 (file)
@@ -6,6 +6,8 @@ description       "Installs and configures Donate Site"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
-depends           "mysql"
 depends           "git"
+depends           "mysql"
+depends           "php"
index 1b3ede31092dcdd6857a5c5f45124c496561cb76..7389db3cf7297af4a8f78a7c320d2712b7fc8646 100644 (file)
 # limitations under the License.
 #
 
+include_recipe "accounts"
 include_recipe "apache"
-include_recipe "mysql"
 include_recipe "git"
+include_recipe "mysql"
+include_recipe "php::fpm"
 
 package %w[
-  php
   php-cli
   php-curl
   php-mysql
   php-gd
 ]
 
-apache_module "php7.2"
-
 apache_module "headers"
+apache_module "proxy"
+apache_module "proxy_fcgi"
 
 passwords = data_bag_item("donate", "passwords")
 
@@ -48,12 +49,13 @@ end
 directory "/srv/donate.openstreetmap.org" do
   owner "donate"
   group "donate"
-  mode 0o755
+  mode "755"
 end
 
 git "/srv/donate.openstreetmap.org" do
   action :sync
-  repository "git://github.com/osmfoundation/donation-drive.git"
+  repository "https://github.com/osmfoundation/donation-drive.git"
+  depth 1
   user "donate"
   group "donate"
 end
@@ -61,14 +63,14 @@ end
 directory "/srv/donate.openstreetmap.org/data" do
   owner "donate"
   group "donate"
-  mode 0o755
+  mode "755"
 end
 
 template "/srv/donate.openstreetmap.org/scripts/db-connect.inc.php" do
   source "db-connect.inc.php.erb"
   owner "root"
   group "donate"
-  mode 0o644
+  mode "644"
   variables :passwords => passwords
 end
 
@@ -78,22 +80,26 @@ ssl_certificate "donate.openstreetmap.org" do
   notifies :reload, "service[apache2]"
 end
 
+php_fpm "donate.openstreetmap.org" do
+  php_admin_values "open_basedir" => "/srv/donate.openstreetmap.org/:/usr/share/php/:/tmp/",
+                   "disable_functions" => "exec,shell_exec,system,passthru,popen,proc_open"
+  prometheus_port 11101
+end
+
 apache_site "donate.openstreetmap.org" do
   template "apache.erb"
 end
 
-template "/etc/cron.d/osmf-donate" do
-  source "cron.erb"
-  owner "root"
-  group "root"
-  mode 0o600
-  variables :passwords => passwords
+cron_d "osmf-donate" do
+  minute "*/2"
+  user "donate"
+  command "cd /srv/donate.openstreetmap.org/scripts/; /usr/bin/php /srv/donate.openstreetmap.org/scripts/update_csv_donate2016.php"
 end
 
 template "/etc/cron.daily/osmf-donate-backup" do
   source "backup.cron.erb"
   owner "root"
   group "root"
-  mode 0o750
+  mode "750"
   variables :passwords => passwords
 end
index 9404ad13ad03e2f6f676fede00989b78087a4957..329dc12bddbfb6e8cffd9aa8a1ba3872e4a0cb37 100644 (file)
@@ -27,9 +27,6 @@
 
   DocumentRoot /srv/donate.openstreetmap.org
 
-  php_admin_value open_basedir /srv/donate.openstreetmap.org/:/usr/share/php/:/tmp/
-  php_admin_value disable_functions "exec,shell_exec,system,passthru,popen,proc_open"
-
   # Alias Dynamic Content to data folder to avoid serving dummy git content
   Alias /donors-eur.csv /srv/donate.openstreetmap.org/data/donors-eur.csv
   Alias /donors.csv /srv/donate.openstreetmap.org/data/donors.csv
   Redirect permanent /server2015 https://donate.openstreetmap.org/
 
   <Directory /srv/donate.openstreetmap.org>
-       Require all granted
+    Require all granted
+
+    <FilesMatch ".+\.ph(ar|p|tml)$">
+      SetHandler "proxy:unix:/run/php/donate.openstreetmap.org.sock|fcgi://127.0.0.1"
+    </FilesMatch>
   </Directory>
 
   <Directory /srv/donate.openstreetmap.org/scripts>
index 92b66cf005bcf36f9dfab5a09937cc2ec47c402f..3782762c339182ad5f8a2eee18f5b626823cc670 100644 (file)
@@ -10,13 +10,12 @@ mkdir $T/osm-donate-$D
 echo '[mysqldump]' > $T/mysqldump.opts
 echo 'user=donate' >> $T/mysqldump.opts
 echo 'password=<%= @passwords["database"] %>' >> $T/mysqldump.opts
-mysqldump --defaults-file=$T/mysqldump.opts --opt donate > $T/osm-donate-$D/osm-donate.sql
+mysqldump --defaults-file=$T/mysqldump.opts --opt --no-tablespaces donate > $T/osm-donate-$D/osm-donate.sql
 ln -s /srv/donate.openstreetmap.org $T/osm-donate-$D/www
 
-export GZIP="--rsyncable -9"
 export RSYNC_RSH="ssh -ax"
 
-nice tar --create --gzip --dereference --directory=$T --file=$T/$B osm-donate-$D
+nice tar --create --dereference --directory=$T osm-donate-$D | nice gzip --rsyncable -9 > $T/$B
 nice rsync --preallocate --fuzzy $T/$B backup::backup
 
 rm -rf $T
diff --git a/cookbooks/donate/templates/default/cron.erb b/cookbooks/donate/templates/default/cron.erb
deleted file mode 100644 (file)
index 42d6c77..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-*/2 * * * * donate cd /srv/donate.openstreetmap.org/scripts/; /usr/bin/php /srv/donate.openstreetmap.org/scripts/update_csv_donate2016.php
index a2a643412d568305b6c98022938f9e93653e6c7d..1de57c968b7eb6c4148fc96ddd9279dd256237df 100644 (file)
@@ -1,4 +1,5 @@
-default[:elasticsearch][:version] = "1.7"
+default[:elasticsearch][:version] = "6.x"
+default[:elasticsearch][:cluster][:name] = "default"
 default[:elasticsearch][:cluster][:routing][:allocation][:disk][:watermark][:low] = "85%"
 default[:elasticsearch][:cluster][:routing][:allocation][:disk][:watermark][:high] = "90%"
 default[:elasticsearch][:cluster][:routing][:allocation][:disk][:watermark][:flood_stage] = "95%"
index 9bab57ae284c0241541563328cce4a559905dc16..37f38ee1a5052f10020f1bcc64d00df82b355814 100644 (file)
@@ -6,3 +6,4 @@ description       "Installs and configures a elasticsearch server"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "apt"
index d2ba1d31b6a1fb5f1527cca3c44f25f3ec85c66b..cd7e8ff0165cea04d206aed537d2e43535bedbe3 100644 (file)
 # limitations under the License.
 #
 
-package %w[
-  default-jre-headless
-  elasticsearch
-]
+include_recipe "apt"
+
+package "default-jre-headless"
+package "elasticsearch"
 
 template "/etc/elasticsearch/elasticsearch.yml" do
   source "elasticsearch.yml.erb"
   user "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[elasticsearch]"
 end
 
index 77b8d87166fceea30b8efa16f70d4f6bdf782350..21e999109794dc7cb5fe7d63a8fafb33bd91e355 100644 (file)
@@ -3,6 +3,7 @@ default[:exim][:relay_to_domains] = []
 default[:exim][:relay_from_hosts] = ["127.0.0.1", "::1"]
 default[:exim][:daemon_smtp_ports] = [25]
 default[:exim][:trusted_users] = []
+default[:exim][:queue_run_max] = 1
 default[:exim][:smarthost_name] = nil
 default[:exim][:smarthost_via] = "mail.openstreetmap.org:26"
 default[:exim][:routes] = {}
index 754ee82ded64e89f82675b5125278125a0150852..cd9da2c453c5459e25d63507affc55ab69014b12 100644 (file)
@@ -6,6 +6,9 @@ description       "Installs and configures exim"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
+depends           "apache"
+depends           "munin"
 depends           "networking"
+depends           "prometheus"
 depends           "ssl"
-depends           "apache"
index 94133183a5ee06760e2632e278e5cbcc419118db..8a1fd5efb562c22d0b7924ca975d191a3dd7eeaf 100644 (file)
@@ -17,7 +17,9 @@
 # limitations under the License.
 #
 
+include_recipe "munin"
 include_recipe "networking"
+include_recipe "prometheus"
 
 package %w[
   exim4
@@ -25,7 +27,9 @@ package %w[
   ssl-cert
 ]
 
-package "exim4-daemon-heavy" if File.exist?("/var/run/clamav/clamd.ctl")
+package "exim4-daemon-heavy" do
+  only_if { ::File.exist?("/var/run/clamav/clamd.ctl") }
+end
 
 group "ssl-cert" do
   action :modify
@@ -50,7 +54,7 @@ else
     key_file "/etc/ssl/private/exim.key"
     owner "root"
     group "ssl-cert"
-    mode 0o640
+    mode "640"
     org "OpenStreetMap"
     email "postmaster@openstreetmap.org"
     common_name node[:fqdn]
@@ -73,22 +77,105 @@ end
 relay_from_hosts = node[:exim][:relay_from_hosts]
 
 if node[:exim][:smarthost_name]
+  search(:node, "roles:gateway") do |gateway|
+    allowed_ips = gateway.interfaces(:role => :internal).map do |interface|
+      "#{interface[:network]}/#{interface[:prefix]}"
+    end
+
+    node.default[:networking][:wireguard][:peers] << {
+      :public_key => gateway[:networking][:wireguard][:public_key],
+      :allowed_ips => allowed_ips,
+      :endpoint => "#{gateway.name}:51820"
+    }
+  end
+
   search(:node, "exim_smarthost_via:#{node[:exim][:smarthost_name]}\\:*").each do |host|
     relay_from_hosts |= host.ipaddresses(:role => :external)
   end
+
+  domains = node[:exim][:certificate_names].select { |c| c =~ /^a\.mx\./ }.collect { |c| c.sub(/^a\.mx./, "") }
+  primary_domain = domains.first
+
+  directory "/srv/mta-sts.#{primary_domain}" do
+    owner "root"
+    group "root"
+    mode "755"
+  end
+
+  domains.each do |domain|
+    template "/srv/mta-sts.#{primary_domain}/#{domain}.txt" do
+      source "mta-sts.erb"
+      owner "root"
+      group "root"
+      mode "644"
+      variables :domain => domain
+    end
+  end
+
+  ssl_certificate "mta-sts.#{primary_domain}" do
+    domains domains.collect { |d| "mta-sts.#{d}" }
+    notifies :reload, "service[apache2]"
+  end
+
+  apache_site "mta-sts.#{primary_domain}" do
+    template "apache-mta-sts.erb"
+    directory "/srv/mta-sts.#{primary_domain}"
+    variables :domains => domains
+  end
 end
 
 file "/etc/exim4/blocked-senders" do
   owner "root"
   group "Debian-exim"
-  mode 0o644
+  mode "644"
+end
+
+if node[:exim][:dkim_selectors]
+  keys = data_bag_item("exim", "dkim")
+
+  template "/etc/exim4/dkim-domains" do
+    owner "root"
+    source "dkim-domains.erb"
+    group "Debian-exim"
+    mode "644"
+  end
+
+  template "/etc/exim4/dkim-selectors" do
+    owner "root"
+    source "dkim-selectors.erb"
+    group "Debian-exim"
+    mode "644"
+  end
+
+  directory "/etc/exim4/dkim-keys" do
+    owner "root"
+    group "Debian-exim"
+    mode "755"
+  end
+
+  node[:exim][:dkim_selectors].each do |domain, _selector|
+    file "/etc/exim4/dkim-keys/#{domain}" do
+      content keys[domain].join("\n")
+      owner "root"
+      group "Debian-exim"
+      mode "640"
+    end
+  end
+end
+
+template "/etc/default/exim4" do
+  source "default.erb"
+  owner "root"
+  group "root"
+  mode "044"
+  notifies :restart, "service[exim4]"
 end
 
 template "/etc/exim4/exim4.conf" do
   source "exim4.conf.erb"
   owner "root"
   group "Debian-exim"
-  mode 0o644
+  mode "644"
   variables :relay_to_domains => relay_to_domains.sort,
             :relay_from_hosts => relay_from_hosts.sort
   notifies :restart, "service[exim4]"
@@ -115,23 +202,27 @@ template "/etc/aliases" do
   source "aliases.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 remote_directory "/etc/exim4/noreply" do
   source "noreply"
   owner "root"
   group "Debian-exim"
-  mode 0o755
+  mode "755"
   files_owner "root"
   files_group "Debian-exim"
-  files_mode 0o755
+  files_mode "755"
   purge true
 end
 
 munin_plugin "exim_mailqueue"
 munin_plugin "exim_mailstats"
 
+prometheus_exporter "exim" do
+  port 9636
+end
+
 if node[:exim][:smarthost_name]
   node[:exim][:daemon_smtp_ports].each do |port|
     firewall_rule "accept-inbound-smtp-#{port}" do
diff --git a/cookbooks/exim/templates/default/apache-mta-sts.erb b/cookbooks/exim/templates/default/apache-mta-sts.erb
new file mode 100644 (file)
index 0000000..82b787f
--- /dev/null
@@ -0,0 +1,34 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:80>
+  ServerName <%= @name %>
+<% @domains.drop(1).each do |domain| -%>
+  ServerAlias mta-sts.<%= domain %>
+<% end -%>
+  ServerAdmin webmaster@openstreetmap.org
+
+  CustomLog /var/log/apache2/<%= @name %>-access.log combined
+  ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+  RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
+</VirtualHost>
+<% @domains.each do |domain| -%>
+
+<VirtualHost *:443>
+  ServerName mta-sts.<%= domain %>
+  ServerAdmin webmaster@openstreetmap.org
+
+  SSLEngine on
+  SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
+  SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
+
+  CustomLog /var/log/apache2/<%= @name %>-access.log combined
+  ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+  Alias /.well-known/mta-sts.txt <%= @directory %>/<%= domain %>.txt
+</VirtualHost>
+<% end -%>
+
+<Directory <%= @directory %>>
+  Require all granted
+</Directory>
diff --git a/cookbooks/exim/templates/default/default.erb b/cookbooks/exim/templates/default/default.erb
new file mode 100644 (file)
index 0000000..2fb3dcc
--- /dev/null
@@ -0,0 +1,23 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# 'combined' -   one daemon running queue and listening on SMTP port
+# 'no'       -   no daemon running the queue
+# 'separate' -   two separate daemons
+# 'ppp'      -   only run queue with /etc/ppp/ip-up.d/exim4.
+# 'nodaemon' - no daemon is started at all.
+# 'queueonly' - only a queue running daemon is started, no SMTP listener.
+# setting this to 'no' will also disable queueruns from /etc/ppp/ip-up.d/exim4
+QUEUERUNNER='combined'
+# how often should we run the queue
+QUEUEINTERVAL='30s'
+# options common to quez-runner and listening daemon
+COMMONOPTIONS=''
+# more options for the daemon/process running the queue (applies to the one
+# started in /etc/ppp/ip-up.d/exim4, too.
+QUEUERUNNEROPTIONS=''
+# special flags given to exim directly after the -q. See exim(8)
+QFLAGS=''
+# options for daemon listening on port 25
+SMTPLISTENEROPTIONS=''
+# only warn once about each error
+E4BCD_WATCH_PANICLOG='once'
diff --git a/cookbooks/exim/templates/default/dkim-domains.erb b/cookbooks/exim/templates/default/dkim-domains.erb
new file mode 100644 (file)
index 0000000..992ac39
--- /dev/null
@@ -0,0 +1,3 @@
+<% node[:exim][:dkim_selectors].each do |domain, _selector| -%>
+*.<%= domain %>: <%= domain %>
+<% end -%>
diff --git a/cookbooks/exim/templates/default/dkim-selectors.erb b/cookbooks/exim/templates/default/dkim-selectors.erb
new file mode 100644 (file)
index 0000000..13078fa
--- /dev/null
@@ -0,0 +1,3 @@
+<% node[:exim][:dkim_selectors].each do |domain, selector| -%>
+<%= domain %>: <%= selector %>
+<% end -%>
index 0a4f1d04f249c3b4bde08863dddac8ffb701f80a..2d1d96e1288751dac4ed8ae2073abe63f089dc9f 100644 (file)
@@ -42,6 +42,7 @@
 ######################################################################
 #                    MAIN CONFIGURATION SETTINGS                     #
 ######################################################################
+#
 
 # Specify your host's canonical name here. This should normally be the fully
 # qualified "official" name of your host. If this option is not set, the
@@ -93,12 +94,13 @@ hostlist   relay_from_hosts = <; <%= @relay_from_hosts.join(" ; ") %>
 # to any other host on the Internet. Such a setting commonly refers to a
 # complete local network as well as the localhost. For example:
 #
-# hostlist relay_from_hosts = 127.0.0.1 : 192.168.0.0/16
+# hostlist relay_from_hosts = <; 127.0.0.1 ; ::1 ; 192.168.0.0/16
 #
 # The "/16" is a bit mask (CIDR notation), not a number of hosts. Note that you
 # have to include 127.0.0.1 if you want to allow processes on your host to send
 # SMTP mail by using the loopback address. A number of MUAs use this method of
-# sending mail.
+# sending mail.  Often, connections are made to "localhost", which might be ::1
+# on IPv6-enabled hosts.  Do not forget CIDR for your IPv6 networks.
 
 # All three of these lists may contain many different kinds of item, including
 # wildcarded names, regular expressions, and file lookups. See the reference
@@ -144,11 +146,7 @@ spamd_address = 127.0.0.1 783
 
 # Allow any client to use TLS.
 
-tls_advertise_hosts = <; !127.0.0.1 ; !::1
-
-# Configured TLS cipher selection.
-
-tls_require_ciphers = <%= node[:ssl][:gnutls_ciphers] %>:%SERVER_PRECEDENCE
+tls_advertise_hosts = *
 
 # Specify the location of the Exim server's TLS certificate and private key.
 # The private key must not be encrypted (password protected). You can put
@@ -164,6 +162,10 @@ tls_certificate = /etc/ssl/certs/exim.pem
 tls_privatekey = /etc/ssl/private/exim.key
 <% end -%>
 
+# Configure TLS cipher selection.
+
+tls_require_ciphers = <%= node[:ssl][:gnutls_ciphers] %>:%SERVER_PRECEDENCE
+
 # In order to support roaming users who wish to send email from anywhere,
 # you may want to make Exim listen on other ports as well as port 25, in
 # case these users need to send email from a network that blocks port 25.
@@ -233,18 +235,26 @@ never_users = root
 host_lookup = *
 
 
-# The settings below, which are actually the same as the defaults in the
-# code, cause Exim to make RFC 1413 (ident) callbacks for all incoming SMTP
-# calls. You can limit the hosts to which these calls are made, and/or change
-# the timeout that is used. If you set the timeout to zero, all RFC 1413 calls
-# are disabled. RFC 1413 calls are cheap and can provide useful information
-# for tracing problem messages, but some hosts and firewalls have problems
-# with them. This can result in a timeout instead of an immediate refused
-# connection, leading to delays on starting up SMTP sessions. (The default was
-# reduced from 30s to 5s for release 4.61.)
+# The settings below cause Exim to make RFC 1413 (ident) callbacks
+# for all incoming SMTP calls. You can limit the hosts to which these
+# calls are made, and/or change the timeout that is used. If you set
+# the timeout to zero, all RFC 1413 calls are disabled. RFC 1413 calls
+# are cheap and can provide useful information for tracing problem
+# messages, but some hosts and firewalls have problems with them.
+# This can result in a timeout instead of an immediate refused
+# connection, leading to delays on starting up SMTP sessions.
+# (The default was reduced from 30s to 5s for release 4.61. and to
+# disabled for release 4.86)
+#
+#rfc1413_hosts = *
+#rfc1413_query_timeout = 5s
+
 
-rfc1413_hosts = *
-rfc1413_query_timeout = 5s
+# Enable an efficiency feature.  We advertise the feature; clients
+# may request to use it.  For multi-recipient mails we then can
+# reject or accept per-user after the message is received.
+#
+prdr_enable = true
 
 
 # By default, Exim expects all envelope addresses to be fully qualified, that
@@ -260,6 +270,12 @@ rfc1413_query_timeout = 5s
 # and/or qualify_recipient (see above).
 
 
+# Unless you run a high-volume site you probably want more logging
+# detail than the default.  Adjust to suit.
+
+log_selector = +all -skip_delivery
+
+
 # If you want Exim to support the "percent hack" for certain domains,
 # uncomment the following line and provide a list of domains. The "percent
 # hack" is the feature by which mail addressed to x%y@z (where z is one of
@@ -304,10 +320,37 @@ timeout_frozen_after = 7d
 # split_spool_directory = true
 
 
-# Log just about everything we can log so that we have the best
-# possible chance of knowing what's going on.
+# If you're in a part of the world where ASCII is not sufficient for most
+# text, then you're probably familiar with RFC2047 message header extensions.
+# By default, Exim adheres to the specification, including a limit of 76
+# characters to a line, with encoded words fitting within a line.
+# If you wish to use decoded headers in message filters in such a way
+# that successful decoding of malformed messages matters, you may wish to
+# configure Exim to be more lenient.
+#
+# check_rfc2047_length = false
+#
+# In particular, the Exim maintainers have had multiple reports of problems
+# from Russian administrators of issues until they disable this check,
+# because of some popular, yet buggy, mail composition software.
+
+
+# If you wish to be strictly RFC compliant, or if you know you'll be
+# exchanging email with systems that are not 8-bit clean, then you may
+# wish to disable advertising 8BITMIME.  Uncomment this option to do so.
+
+# accept_8bitmime = false
 
-log_selector = +all -skip_delivery
+
+# Exim does not make use of environment variables itself. However,
+# libraries that Exim uses (e.g. LDAP) depend on specific environment settings.
+# There are two lists: keep_environment for the variables we trust, and
+# add_environment for variables we want to set to a specific value.
+# Note that TZ is handled separately by the timezone runtime option
+# and TIMEZONE_DEFAULT buildtime option.
+
+# keep_environment = ^LDAP
+# add_environment = PATH=/usr/bin::/bin
 
 
 # Define trusted users.
@@ -315,10 +358,10 @@ log_selector = +all -skip_delivery
 trusted_users = <%= node[:exim][:trusted_users].join(" : ") %>
 
 
-# Don't keep any environment when starting programs - this is the
-# default but setting it stops exim warning
+# Do all deliveries via a limited set of queues.
 
-keep_environment =
+queue_only = true
+queue_run_max = <%= node[:exim][:queue_run_max] %>
 
 
 
@@ -384,7 +427,7 @@ acl_check_rcpt:
 
   deny    message       = Restricted characters in address
           domains       = !+local_domains
-          local_parts   = ^[./|] : ^.*[@!] : ^.*/\\.\\./
+          local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
   #############################################################################
 
   # Block bounces to selected addresses
@@ -513,9 +556,13 @@ acl_check_data:
          !hosts      = +relay_from_hosts
           message    = This message failed local spam checks.
 
-  # Accept the message.
+  # Accept messages from relay hosts without modification.
 
-  accept
+  accept  hosts      = +relay_from_hosts
+
+  # Accept messages from external hosts and add authentication results.
+
+  accept  add_header = :at_start:${authresults {$primary_hostname}}
 
 
 
@@ -641,7 +688,7 @@ smarthost:
 dnslookup:
   driver = dnslookup
   domains = ! +local_domains
-  transport = remote_smtp
+  transport = signed_smtp
   same_domain_copy_routing = yes
   ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
   no_more
@@ -669,6 +716,20 @@ remote_smtp:
   tls_require_ciphers = <%= node[:ssl][:gnutls_ciphers] %>:%LATEST_RECORD_VERSION
 
 
+# This transport is used for delivering DKIM signed messages over SMTP connections.
+
+signed_smtp:
+  driver = smtp
+  dkim_domain = ${lookup{${domain:$h_from:}}partial-lsearch{/etc/exim4/dkim-domains}{$value}}
+  dkim_selector = ${lookup{$dkim_domain}lsearch{/etc/exim4/dkim-selectors}{$value}}
+  dkim_private_key = /etc/exim4/dkim-keys/${dkim_domain}
+  dkim_identity = ${lc:${address:$h_from:}}
+  dkim_timestamps = 1209600
+  multi_domain = false
+  hosts_try_dane =
+  tls_require_ciphers = <%= node[:ssl][:gnutls_ciphers] %>:%LATEST_RECORD_VERSION
+
+
 # This transport is used for handling pipe deliveries generated by alias or
 # .forward files. If the pipe generates any standard output, it is returned
 # to the sender of the message as a delivery error. Set return_fail_output
@@ -718,7 +779,7 @@ noreply:
   to = $sender_address
   subject = Re: $header_subject:
   headers = MIME-Version: 1.0\nContent-Type: text/plain; charset=utf-8
-  file = /etc/exim4/noreply/$local_part
+  file = /etc/exim4/noreply/$local_part_data
   user = Debian-exim
   group = Debian-exim
 
diff --git a/cookbooks/exim/templates/default/mta-sts.erb b/cookbooks/exim/templates/default/mta-sts.erb
new file mode 100644 (file)
index 0000000..bd237b1
--- /dev/null
@@ -0,0 +1,4 @@
+version: STSv1
+mode: enforce
+mx: *.mx.<%= @domain %>
+max_age: 31536000
index 6ff596b4369fc4223311194a84f0cea4a4dc3042..93f21f14d0e8c5edb433eff775452eec8ed784c0 100644 (file)
@@ -6,3 +6,4 @@ description       "Configures fail2ban"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "munin"
index a002fe13196fc2ff4debb663dd25392a4f30a57a..e0e8e2372748a3d581a357b824972ad4f8bc52ae 100644 (file)
 # limitations under the License.
 #
 
+include_recipe "munin"
+
 package "fail2ban"
 
 template "/etc/fail2ban/jail.d/00-default.conf" do
   source "jail.default.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
+  notifies :restart, "service[fail2ban]"
+end
+
+template "/etc/fail2ban/paths-overrides.local" do
+  source "paths-overrides.local.erb"
+  owner "root"
+  group "root"
+  mode "644"
   notifies :restart, "service[fail2ban]"
 end
 
index d37ba4bb2e83a64a5035df4438493b3e17202948..3cd173eee70e937b19e86e41c74677874a5ea6f4 100644 (file)
@@ -19,7 +19,7 @@
 
 default_action :create
 
-property :filter, :kind_of => String, :name_attribute => true
+property :filter, :kind_of => String, :name_property => true
 property :source, :kind_of => String
 property :failregex, :kind_of => [String, Array]
 property :ignoreregex, :kind_of => [String, Array]
@@ -30,7 +30,7 @@ action :create do
       source new_resource.source
       owner "root"
       group "root"
-      mode 0o644
+      mode "644"
     end
   else
     template "/etc/fail2ban/filter.d/#{new_resource.filter}.conf" do
@@ -38,7 +38,7 @@ action :create do
       source "filter.erb"
       owner "root"
       group "root"
-      mode 0o644
+      mode "644"
       variables :failregex => new_resource.failregex,
                 :ignoreregex => new_resource.ignoreregex
     end
index c07914d2cd4280bbaec8e824941b144c1f441b67..6ff5307e3bd939775f273718ab59a4bdc8e7f60c 100644 (file)
@@ -19,7 +19,7 @@
 
 default_action :create
 
-property :jail, :kind_of => String, :name_attribute => true
+property :jail, :kind_of => String, :name_property => true
 property :filter, :kind_of => String
 property :logpath, :kind_of => String
 property :protocol, :kind_of => String
@@ -33,7 +33,7 @@ action :create do
     source "jail.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables :name => new_resource.jail,
               :filter => new_resource.filter,
               :logpath => new_resource.logpath,
similarity index 57%
rename from cookbooks/dns/templates/default/cron.erb
rename to cookbooks/fail2ban/templates/default/paths-overrides.local.erb
index 5ab9b3af7671c69d85f9a615c0ac5f9c6588c691..7fbd19a79242ca205e942a37cb2b6e1b5c09abf4 100644 (file)
@@ -1,3 +1,4 @@
 # DO NOT EDIT - This file is being maintained by Chef
 
-*/3 * * * * git /usr/local/bin/dns-check
+[DEFAULT]
+sshd_backend = systemd
diff --git a/cookbooks/forum/attributes/default.rb b/cookbooks/forum/attributes/default.rb
new file mode 100644 (file)
index 0000000..9f4114f
--- /dev/null
@@ -0,0 +1,2 @@
+# Enable the "forum" role
+default[:accounts][:users][:forum][:status] = :role
index 21edbfe64551245457bc39d4a282a1c5cb4d8a6f..6721b1ca1beedd0f5a27d4a04473619eb653bb1c 100644 (file)
@@ -6,6 +6,8 @@ description       "Installs and configures a roundup server"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
 depends           "git"
 depends           "mysql"
+depends           "php"
index e75e5a32133febcec3c9fb7f42c177562f1a563f..728408a0c8d7e91e2be06398fba86a4ed0a67ada 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+
+include_recipe "accounts"
 include_recipe "apache"
 include_recipe "git"
 include_recipe "mysql"
+include_recipe "php::fpm"
+
+cache_dir = Chef::Config[:file_cache_path]
 
 passwords = data_bag_item("forum", "passwords")
 
 package %w[
-  php
   php-cli
   php-mysql
   php-xml
   php-apcu
+  unzip
 ]
 
-apache_module "php7.2"
+apache_module "env"
 apache_module "rewrite"
 
 ssl_certificate "forum.openstreetmap.org" do
@@ -38,6 +43,12 @@ ssl_certificate "forum.openstreetmap.org" do
   notifies :reload, "service[apache2]"
 end
 
+php_fpm "forum.openstreetmap.org" do
+  php_admin_values "open_basedir" => "/srv/forum.openstreetmap.org/html/:/usr/share/php/:/tmp/",
+                   "disable_functions" => "exec,shell_exec,system,passthru,popen,proc_open"
+  prometheus_port 9253
+end
+
 apache_site "forum.openstreetmap.org" do
   template "apache.erb"
 end
@@ -45,7 +56,7 @@ end
 directory "/srv/forum.openstreetmap.org" do
   owner "forum"
   group "forum"
-  mode 0o755
+  mode "755"
 end
 
 git "/srv/forum.openstreetmap.org/html/" do
@@ -58,41 +69,41 @@ git "/srv/forum.openstreetmap.org/html/" do
   notifies :reload, "service[apache2]"
 end
 
-remote_file "/var/cache/chef/air3_v0.8.zip" do
+remote_file "#{cache_dir}/air3_v0.8.zip" do
   action :create_if_missing
   source "https://fluxbb.org/resources/styles/air3/releases/0.8/air3_v0.8.zip"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   backup false
 end
 
-execute "/var/cache/chef/air3_v0.8.zip" do
+execute "#{cache_dir}/air3_v0.8.zip" do
   action :nothing
-  command "unzip -o -qq /var/cache/chef/air3_v0.8.zip Air3.css Air3/*"
+  command "unzip -o -qq #{cache_dir}/air3_v0.8.zip Air3.css 'Air3/*'"
   cwd "/srv/forum.openstreetmap.org/html/style"
   user "forum"
   group "forum"
-  subscribes :run, "remote_file[/var/cache/chef/air3_v0.8.zip]", :immediately
+  subscribes :run, "remote_file[#{cache_dir}/air3_v0.8.zip]", :immediately
 end
 
 directory "/srv/forum.openstreetmap.org/html/cache/" do
   owner "www-data"
   group "www-data"
-  mode 0o755
+  mode "755"
 end
 
 directory "/srv/forum.openstreetmap.org/html/img/avatars/" do
   owner "www-data"
   group "www-data"
-  mode 0o755
+  mode "755"
 end
 
 template "/srv/forum.openstreetmap.org/html/config.php" do
   source "config.php.erb"
   owner "forum"
   group "www-data"
-  mode 0o440
+  mode "440"
   variables :passwords => passwords
 end
 
@@ -108,6 +119,6 @@ template "/etc/cron.daily/forum-backup" do
   source "backup.cron.erb"
   owner "root"
   group "root"
-  mode 0o750
+  mode "750"
   variables :passwords => passwords
 end
index e84f1e35b5e1e3b69873c4def075a1f1af20d0bf..d51786b26b707487bff0f29661dff8d3c396e84f 100644 (file)
 
        DocumentRoot /srv/forum.openstreetmap.org/html
 
-       php_admin_value open_basedir /srv/forum.openstreetmap.org/html/:/usr/share/php/:/tmp/
-       php_admin_value disable_functions "exec,shell_exec,system,passthru,popen,proc_open"
-       php_value upload_max_filesize 70M
-       php_value post_max_size 100M
+       <FilesMatch ".+\.ph(ar|p|tml)$">
+               SetHandler "proxy:unix:/run/php/forum.openstreetmap.org.sock|fcgi://127.0.0.1"
+       </FilesMatch>
 </VirtualHost>
 
 <Directory /srv/forum.openstreetmap.org/html>
@@ -55,5 +54,7 @@
 </Directory>
 
 <Directory /srv/forum.openstreetmap.org/html/img>
-       php_admin_flag engine off
+       <FilesMatch ".+\.ph(ar|p|tml)$">
+               SetHandler None
+       </FilesMatch>
 </Directory>
index c3475b87663bd2dfd47b39b7161424382c76699f..517f71634999249eefe6b533c622d0104e21618b 100644 (file)
@@ -10,13 +10,12 @@ mkdir $T/forum-$D
 echo '[mysqldump]' > $T/mysqldump.opts
 echo 'user=forum' >> $T/mysqldump.opts
 echo 'password=<%= @passwords["database"] %>' >> $T/mysqldump.opts
-mysqldump --defaults-file=$T/mysqldump.opts --opt forum > $T/forum-$D/forum.sql
+mysqldump --defaults-file=$T/mysqldump.opts --opt --no-tablespaces forum > $T/forum-$D/forum.sql
 ln -s /srv/forum.openstreetmap.org $T/forum-$D/www
 
-export GZIP="--rsyncable -9"
 export RSYNC_RSH="ssh -ax"
 
-nice tar --create --gzip --dereference --directory=$T --file=$T/$B forum-$D
+nice tar --create --dereference --directory=$T forum-$D | nice gzip --rsyncable -9 > $T/$B
 nice rsync --preallocate --fuzzy $T/$B backup::backup
 
 rm -rf $T
index d951a2a0dca8e7699d25615ea7286acdb4aa590c..84d6b24b18b24fb53e38d0eee8809aa7f9a4e1cc 100644 (file)
@@ -25,6 +25,7 @@ mediawiki_site "board.osmfoundation.org" do
   sitename "OSMF Board Wiki"
   metanamespace "OSMFBoard"
   directory "/srv/board.osmfoundation.org"
+  fpm_prometheus_port 11004
   database_name "board-wiki"
   database_user "board-wikiuser"
   database_password passwords["board"]["database"]
@@ -36,10 +37,11 @@ mediawiki_site "board.osmfoundation.org" do
   private_site true
   recaptcha_public_key "6LflIQATAAAAAMXyDWpba-FgipVzE-aGF4HIR59N"
   recaptcha_private_key passwords["board"]["recaptcha"]
+  version "1.34"
 end
 
 cookbook_file "/srv/board.osmfoundation.org/Wiki.png" do
   owner node[:mediawiki][:user]
   group node[:mediawiki][:group]
-  mode 0o644
+  mode "644"
 end
index 13238888e2cfd346ac200916e81a5b4e4e8865b0..2eff0db56596f9e4cf9f371f1f13c493046c9f77 100644 (file)
@@ -25,6 +25,7 @@ mediawiki_site "dwg.osmfoundation.org" do
   sitename "OSMF Data Working Group Wiki"
   metanamespace "OSMFDWG"
   directory "/srv/dwg.osmfoundation.org"
+  fpm_prometheus_port 11002
   database_name "dwg-wiki"
   database_user "dwg-wikiuser"
   database_password passwords["dwg"]["database"]
@@ -36,10 +37,11 @@ mediawiki_site "dwg.osmfoundation.org" do
   private_site true
   recaptcha_public_key "6LflIQATAAAAAMXyDWpba-FgipVzE-aGF4HIR59N"
   recaptcha_private_key passwords["dwg"]["recaptcha"]
+  version "1.34"
 end
 
 cookbook_file "/srv/dwg.osmfoundation.org/Wiki.png" do
   owner node[:mediawiki][:user]
   group node[:mediawiki][:group]
-  mode 0o644
+  mode "644"
 end
index d347528c8fe3887c36e644cfbfe84c574ba3f697..60bb76fd9a5ef0d8842b74bb7328af5e9abe6df6 100644 (file)
@@ -25,6 +25,7 @@ mediawiki_site "mwg.osmfoundation.org" do
   sitename "OSMF Membership Working Group Wiki"
   metanamespace "OSMFMWG"
   directory "/srv/mwg.osmfoundation.org"
+  fpm_prometheus_port 11003
   database_name "mwg_wiki"
   database_user "mwg_wikiuser"
   database_password passwords["mwg"]["database"]
@@ -36,10 +37,11 @@ mediawiki_site "mwg.osmfoundation.org" do
   private_site true
   recaptcha_public_key "6LflIQATAAAAAMXyDWpba-FgipVzE-aGF4HIR59N"
   recaptcha_private_key passwords["mwg"]["recaptcha"]
+  version "1.34"
 end
 
 cookbook_file "/srv/mwg.osmfoundation.org/Wiki.png" do
   owner node[:mediawiki][:user]
   group node[:mediawiki][:group]
-  mode 0o644
+  mode "644"
 end
index b60d02bac284c6394c02391ccb9ea19c59a1de1a..31d41aa1fdd85c491b6594fe0f2a2ae6fe09a27c 100644 (file)
@@ -21,9 +21,14 @@ include_recipe "apache"
 include_recipe "git"
 
 package %w[
+  gcc
+  g++
+  make
   ruby
   ruby-dev
+  libssl-dev
   zlib1g-dev
+  pkg-config
 ]
 
 gem_package "bundler" do
@@ -32,14 +37,15 @@ end
 
 git "/srv/operations.osmfoundation.org" do
   action :sync
-  repository "git://github.com/openstreetmap/owg-website.git"
+  repository "https://github.com/openstreetmap/owg-website.git"
+  depth 1
   user "root"
   group "root"
   notifies :run, "execute[/srv/operations.osmfoundation.org/Gemfile]"
 end
 
 directory "/srv/operations.osmfoundation.org/_site" do
-  mode 0o755
+  mode "755"
   owner "nobody"
   group "nogroup"
 end
@@ -47,7 +53,7 @@ end
 # Workaround https://github.com/jekyll/jekyll/issues/7804
 # by creating a .jekyll-cache folder
 directory "/srv/operations.osmfoundation.org/.jekyll-cache" do
-  mode 0o755
+  mode "755"
   owner "nobody"
   group "nogroup"
 end
@@ -62,8 +68,7 @@ execute "/srv/operations.osmfoundation.org/Gemfile" do
 end
 
 execute "/srv/operations.osmfoundation.org" do
-  action :nothing
-  command "bundle exec jekyll build --trace --baseurl=https://operations.osmfoundation.org"
+  command "bundle exec jekyll build --trace"
   cwd "/srv/operations.osmfoundation.org"
   user "nobody"
   group "nogroup"
index b05c2ad26ca57670a6f53e913aaa73b6774fbf39..e635b536a971c78c6f8316f77661e219cb348168 100644 (file)
@@ -26,6 +26,11 @@ mediawiki_site "wiki.osmfoundation.org" do
            "foundation.openstreetmap.org", "foundation.osm.org"]
   sitename "OpenStreetMap Foundation"
   directory "/srv/wiki.osmfoundation.org"
+  fpm_max_children 20
+  fpm_start_servers 5
+  fpm_min_spare_servers 5
+  fpm_max_spare_servers 10
+  fpm_prometheus_port 11001
   database_name "osmf-wiki"
   database_user "osmf-wikiuser"
   database_password passwords["wiki"]["database"]
@@ -39,17 +44,18 @@ mediawiki_site "wiki.osmfoundation.org" do
   recaptcha_public_key "6LflIQATAAAAAMXyDWpba-FgipVzE-aGF4HIR59N"
   recaptcha_private_key passwords["wiki"]["recaptcha"]
   extra_file_extensions ["mp3"]
+  version "1.34"
 end
 
 mediawiki_skin "osmf" do
   site "wiki.osmfoundation.org"
-  repository "git://github.com/openstreetmap/mediawiki-skins-osmf.git"
+  repository "https://github.com/openstreetmap/mediawiki-skins-osmf.git"
   revision "master"
 end
 
 mediawiki_skin "OSMFoundation" do
   site "wiki.osmfoundation.org"
-  repository "git://github.com/osmfoundation/osmf-mediawiki-skin.git"
+  repository "https://github.com/osmfoundation/osmf-mediawiki-skin.git"
   revision "master"
   legacy false
 end
@@ -57,5 +63,5 @@ end
 cookbook_file "/srv/wiki.osmfoundation.org/Wiki.png" do
   owner node[:mediawiki][:user]
   group node[:mediawiki][:group]
-  mode 0o644
+  mode "644"
 end
index d2c42100c7aee035f1af9b8e1e00789b77f43838..28d69a7514bd1d7479942cda001d917678d5ca7c 100644 (file)
@@ -26,14 +26,14 @@ template "/etc/vsftpd.conf" do
   source "vsftpd.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 template "/etc/pam.d/vsftpd" do
   source "pam-vsftpd.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 service "vsftpd" do
index 4ce6925bb6c38453b91a7f646262dbdee0d7b178..b912c744291a9353452ca7fc6aa6092cf02f2c9e 100644 (file)
@@ -6,4 +6,6 @@ description       "Installs and configures a geographic DNS server"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "geoipupdate"
+depends           "networking"
 depends           "systemd"
index f24f1b8deecaadc03ec803e555e530d1a3a31b9f..43643c2f9bd0ba0d227a10d873baf0051fef575a 100644 (file)
 # limitations under the License.
 #
 
+include_recipe "geoipupdate"
+
 package %w[
-  geoipupdate
   gdnsd
 ]
 
-execute "geoipdate" do
-  command "geoipupdate"
-  user "root"
-  group "root"
-  not_if { ::File.exist?("/var/lib/GeoIP/GeoLite2-Country.mmdb") }
-end
-
 directory "/etc/gdnsd/config.d" do
   owner "nobody"
   group "nogroup"
-  mode 0o755
+  mode "755"
+end
+
+%w[tile nominatim].each do |zone|
+  %w[map resource weighted].each do |type|
+    template "/etc/gdnsd/config.d/#{zone}.#{type}" do
+      action :create_if_missing
+      source "zone.#{type}.erb"
+      owner "nobody"
+      group "nogroup"
+      mode "644"
+      variables :zone => zone
+    end
+  end
 end
 
 template "/etc/gdnsd/config" do
   source "config.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[gdnsd]"
 end
 
@@ -47,7 +54,7 @@ template "/etc/gdnsd/zones/geo.openstreetmap.org" do
   source "geo.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[gdnsd]"
 end
 
index 38c17dc10611ffdd16938a817a76592821e17638..6ceafc7375cf3c407df14543470d3d9ef197325c 100644 (file)
@@ -1,4 +1,5 @@
 options => {
+  include_optional_ns = true
   listen => [ <%= node.ipaddresses(:role => :external).join(", ") %> ]
 }
         
@@ -6,9 +7,15 @@ plugins => {
   geoip => {
     maps => {
       $include{config.d/tile.map}
+      $include{config.d/nominatim.map}
     }
     resources => {
       $include{config.d/tile.resource}
+      $include{config.d/nominatim.resource}
     }
+  },
+  weighted => {
+    $include{config.d/tile.weighted}
+    $include{config.d/nominatim.weighted}
   }
 }
index 7f33a37607c7272c81e02838421ab26df7d693f9..9e306421879f7f5e09868043ca18d98f021d1796 100644 (file)
@@ -1,18 +1,19 @@
 $TTL 86400
 
-@      SOA     a.ns.openstreetmap.org. hostmaster.openstreetmap.org. (
-       1       ; serial
-       86400   ; refresh
-       172800  ; retry
-       604800  ; expire
-       3600    ; ncache
+@              SOA     saphira.openstreetmap.org. hostmaster.openstreetmap.org. (
+               3       ; serial
+               86400   ; refresh
+               7200    ; retry
+               604800  ; expire
+               3600    ; ncache
 )
 
-@      86400   NS      a.ns.openstreetmap.org.
-@      86400   NS      b.ns.openstreetmap.org.
-@      86400   NS      c.ns.openstreetmap.org.
-@      86400   NS      d.ns.openstreetmap.org.
-@      86400   NS      e.ns.openstreetmap.org.
-@      86400   NS      f.ns.openstreetmap.org.
+@              86400   NS      balerion.openstreetmap.org.
+@              86400   NS      chrysophylax.openstreetmap.org.
+@              86400   NS      katie.openstreetmap.org.
+@              86400   NS      saphira.openstreetmap.org.
+@              86400   NS      stormfly-04.openstreetmap.org.
+@              86400   NS      ridgeback.openstreetmap.org.
 
-tile   600     DYNC    geoip!tile
+tile           300     DYNC    geoip!tile
+nominatim      300     DYNC    geoip!nominatim
diff --git a/cookbooks/geodns/templates/default/zone.map.erb b/cookbooks/geodns/templates/default/zone.map.erb
new file mode 100644 (file)
index 0000000..25bf3ad
--- /dev/null
@@ -0,0 +1,3 @@
+<%= @zone %> => {
+  datacenters => [dummy]
+}
diff --git a/cookbooks/geodns/templates/default/zone.resource.erb b/cookbooks/geodns/templates/default/zone.resource.erb
new file mode 100644 (file)
index 0000000..3c1426b
--- /dev/null
@@ -0,0 +1,6 @@
+<%= @zone %> => {
+  map => <%= @zone %>
+  dcmap => {
+    dummy => dummy.example.com.
+  }
+}
diff --git a/cookbooks/geodns/templates/default/zone.weighted.erb b/cookbooks/geodns/templates/default/zone.weighted.erb
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/cookbooks/geoipupdate/README.md b/cookbooks/geoipupdate/README.md
new file mode 100644 (file)
index 0000000..5eb9966
--- /dev/null
@@ -0,0 +1,4 @@
+# geoipupdate Cookbook
+
+This cookbook installs and configures geoipupdate, a tool to keep MaxMind
+GeoIP databases up to date.
diff --git a/cookbooks/geoipupdate/attributes/default.rb b/cookbooks/geoipupdate/attributes/default.rb
new file mode 100644 (file)
index 0000000..3165aa1
--- /dev/null
@@ -0,0 +1,4 @@
+default[:geoipupdate][:account] = "149244"
+default[:geoipupdate][:editions] = %w[GeoLite2-ASN GeoLite2-City GeoLite2-Country]
+
+default[:apt][:sources] |= ["maxmind"]
diff --git a/cookbooks/geoipupdate/metadata.rb b/cookbooks/geoipupdate/metadata.rb
new file mode 100644 (file)
index 0000000..ccc09f6
--- /dev/null
@@ -0,0 +1,10 @@
+name              "geoipupdate"
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache-2.0"
+description       "Installs and configures geoipupdate"
+
+version           "1.0.0"
+supports          "ubuntu"
+depends           "apt"
+depends           "systemd"
diff --git a/cookbooks/geoipupdate/recipes/default.rb b/cookbooks/geoipupdate/recipes/default.rb
new file mode 100644 (file)
index 0000000..fedae00
--- /dev/null
@@ -0,0 +1,61 @@
+#
+# Cookbook:: geoipdate
+# Recipe:: default
+#
+# Copyright:: 2020, OpenStreetMap Foundation
+#
+# 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
+#
+#     https://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.
+#
+
+include_recipe "apt"
+
+license_keys = data_bag_item("geoipupdate", "license-keys")
+
+package "geoipupdate"
+
+template "/etc/GeoIP.conf" do
+  source "GeoIP.conf.erb"
+  owner "root"
+  group "root"
+  mode "644"
+  variables :license_keys => license_keys
+end
+
+execute "geoipupdate" do
+  command "geoipupdate"
+  user "root"
+  group "root"
+  not_if { ENV.key?("TEST_KITCHEN") || node[:geoipupdate][:editions].all? { |edition| ::File.exist?("/usr/share/GeoIP/#{edition}.mmdb") } }
+end
+
+systemd_service "geoipupdate" do
+  description "Update GeoIP databases"
+  user "root"
+  exec_start "/usr/bin/geoipupdate"
+  private_tmp true
+  private_devices true
+  protect_system "strict"
+  protect_home true
+  read_write_paths "/usr/share/GeoIP"
+end
+
+systemd_timer "geoipupdate" do
+  description "Update GeoIP databases"
+  on_boot_sec "15m"
+  on_unit_active_sec "7d"
+  randomized_delay_sec "4h"
+end
+
+service "geoipupdate.timer" do
+  action [:enable, :start]
+end
diff --git a/cookbooks/geoipupdate/templates/default/GeoIP.conf.erb b/cookbooks/geoipupdate/templates/default/GeoIP.conf.erb
new file mode 100644 (file)
index 0000000..9caa330
--- /dev/null
@@ -0,0 +1,5 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+AccountID <%= node[:geoipupdate][:account] %>
+LicenseKey <%= @license_keys[node[:geoipupdate][:account]] %>
+EditionIDs <%= Array(node[:geoipupdate][:editions]).join(" ") %>
index 2d89a83de9e5c9765075b1169fd1a9a43c052eba..7a4209f5d007809dec252284416562da0d31f01f 100644 (file)
@@ -1,5 +1,9 @@
+default[:git][:host] = "git.openstreetmap.org"
 default[:git][:directory] = "/var/lib/git"
 default[:git][:public_user] = "git"
 default[:git][:public_group] = "git"
 default[:git][:private_user] = "git"
 default[:git][:private_group] = "git"
+default[:git][:private_nodes] = "fqdn:*"
+
+default[:apt][:sources] |= ["git-core"]
index 003590d110f9e817758578e5b8094e2223aec4c6..b86267bd2112d62a16c4a34db405c3cfc7aa4726 100644 (file)
@@ -6,5 +6,7 @@ description       "Installs and configures git"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
+depends           "apt"
 depends           "networking"
index 3f93f651ccd8e04d0ddb7e5e83b2430ed414b746..49d43ae8225b62b2168fbd502cf4bf3ec34ea6c3 100644 (file)
@@ -17,4 +17,6 @@
 # limitations under the License.
 #
 
+include_recipe "apt"
+
 package "git"
index 4a98818e32880ce109eb561317d83a52f5040511..9b4e06a4514c0b8b0114ce972e46d8e2dbc532eb 100644 (file)
 # limitations under the License.
 #
 
+node.default[:accounts][:users][:git][:status] = :role
+
+include_recipe "accounts"
+include_recipe "apt"
 include_recipe "networking"
 
 git_directory = node[:git][:directory]
@@ -24,19 +28,19 @@ git_directory = node[:git][:directory]
 directory git_directory do
   owner "root"
   group "root"
-  mode 0o775
+  mode "775"
 end
 
 directory "#{git_directory}/public" do
   owner node[:git][:public_user]
   group node[:git][:public_group]
-  mode 0o2775
+  mode "2775"
 end
 
 directory "#{git_directory}/private" do
   owner node[:git][:private_user]
   group node[:git][:private_group]
-  mode 0o2775
+  mode "2775"
 end
 
 Dir.glob("#{git_directory}/*/*.git").each do |repository|
@@ -44,7 +48,7 @@ Dir.glob("#{git_directory}/*/*.git").each do |repository|
     source "post-update.erb"
     owner "root"
     group node[:git][:group]
-    mode 0o755
+    mode "755"
   end
 end
 
@@ -52,5 +56,5 @@ template "/etc/cron.daily/git-backup" do
   source "backup.cron.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
index 468074e2c8d027317b601246521a756a9fa3affd..7e1f38cc26c1bd4da1a50ff38fa902c4a076565e 100644 (file)
@@ -29,20 +29,20 @@ template "/etc/gitweb.conf" do
   source "gitweb.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 directory "/srv/#{git_site}" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 template "/srv/#{git_site}/robots.txt" do
   source "robots.txt.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 ssl_certificate git_site do
index 9ec36f7d85a72d771cdfb238ce1c080c7cd670c9..30685fad936f7f76446b593092c4e9c9943554a2 100644 (file)
 
         SetEnv GIT_PROJECT_ROOT /var/lib/git
         SetEnv GIT_HTTP_EXPORT_ALL
+        SetEnv GIT_HTTP_MAX_REQUEST_BUFFER 100M
+
+        SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=$0
+
+        # KeepaliveTimeout longer than git config uploadpack.keepalive 5 second default
+        KeepAliveTimeout 20
 
         ScriptAlias /public /usr/lib/git-core/git-http-backend/public
         ScriptAlias /private /usr/lib/git-core/git-http-backend/private
         <Location />
                   Require all granted
         </Location>
+<% unless @private_allowed.empty? -%>
 
         <Location /private>
                   Require ip <%= @private_allowed.sort.join(" ") %>
         </Location>
+<% end -%>
 
         <Location /private/chef.git>
                   Require all denied
index 5a9d01284e38a98015bcbab877f10b57c6425853..63882720f436b1682647d8b7d5d5323aee837a71 100644 (file)
@@ -8,10 +8,9 @@ B=git-$D.tar.gz
 
 ln -s /var/lib/git $T/git-$D
 
-export GZIP="--rsyncable -9"
 export RSYNC_RSH="ssh -ax"
 
-nice tar --create --gzip --dereference --directory=$T --file=$T/$B git-$D
+nice tar --create --dereference --directory=$T git-$D | nice gzip --rsyncable -9 > $T/$B
 nice rsync --preallocate --fuzzy $T/$B backup::backup
 
 rm -rf $T
diff --git a/cookbooks/gps-tile/attributes/default.rb b/cookbooks/gps-tile/attributes/default.rb
new file mode 100644 (file)
index 0000000..61ab02a
--- /dev/null
@@ -0,0 +1 @@
+default[:accounts][:users][:gpstile][:status] = :role
index e5818349d92e3e34ec6ab867354d71cd23f104ba..cb62f1a177276bf4fdd171932c29255976605ff6 100644 (file)
@@ -6,7 +6,7 @@
     <link rel="stylesheet" href="map.css" type="text/css" media="all" />
     <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.0/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="anonymous" />
     <script src="https://unpkg.com/leaflet@1.3.0/dist/leaflet.js" integrity="sha512-C7BBF9irt5R7hqbUm2uxtODlUVs+IsNu2UULGuZN7gM+k/mmeG4xvIEac01BtQa4YIkUpp23zZC4wIwuXaPMQA==" crossorigin="anonymous"></script>
-    <script src="//code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
     <script type="text/javascript" src="map.js"></script>
   </head>
   <body>
index 78acecfa55b3cfb4c3a7b7c2a9ab8ae52e0cb155..c23644f44d5e12221dec270dc92e0deacc7b2c21 100644 (file)
@@ -6,5 +6,8 @@ description       "Configures a GPS tile server"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
+depends           "git"
+depends           "memcached"
 depends           "systemd"
index 5de9d5573f326a1709a5e9caa4b7a4c725ea59d6..21a515034978ca31bf19a034e3a18b94e9ff8f1e 100644 (file)
 # limitations under the License.
 #
 
+include_recipe "accounts"
 include_recipe "apache"
+include_recipe "git"
+include_recipe "memcached"
 
 package %w[
   make
@@ -35,20 +38,21 @@ package %w[
 directory "/srv/gps-tile.openstreetmap.org" do
   owner "gpstile"
   group "gpstile"
-  mode 0o755
+  mode "755"
 end
 
 git "/srv/gps-tile.openstreetmap.org/import" do
   action :sync
-  repository "git://github.com/ericfischer/gpx-import.git"
+  repository "https://github.com/ericfischer/gpx-import.git"
   revision "live"
+  depth 1
   user "gpstile"
   group "gpstile"
 end
 
 execute "/srv/gps-tile.openstreetmap.org/import/src/Makefile" do
   action :nothing
-  command "make"
+  command "make DB=none LDFLAGS=-lm"
   cwd "/srv/gps-tile.openstreetmap.org/import/src"
   user "gpstile"
   group "gpstile"
@@ -57,8 +61,9 @@ end
 
 git "/srv/gps-tile.openstreetmap.org/datamaps" do
   action :sync
-  repository "git://github.com/ericfischer/datamaps.git"
+  repository "https://github.com/ericfischer/datamaps.git"
   revision "live"
+  depth 1
   user "gpstile"
   group "gpstile"
 end
@@ -74,8 +79,9 @@ end
 
 git "/srv/gps-tile.openstreetmap.org/updater" do
   action :sync
-  repository "git://github.com/ericfischer/gpx-updater.git"
+  repository "https://github.com/ericfischer/gpx-updater.git"
   revision "live"
+  depth 1
   user "gpstile"
   group "gpstile"
 end
@@ -105,10 +111,10 @@ remote_directory "/srv/gps-tile.openstreetmap.org/html" do
   source "html"
   owner "gpstile"
   group "gpstile"
-  mode 0o755
+  mode "755"
   files_owner "gpstile"
   files_group "gpstile"
-  files_mode 0o644
+  files_mode "644"
 end
 
 apache_module "headers"
index 2619fd5497745302b051851d7e3d02ffa7fd6266..bbe44348e69f5f852af112d4f25a3993560acc36 100644 (file)
@@ -1,6 +1,8 @@
 default[:hardware][:modules] = %w[lp]
 default[:hardware][:grub][:cmdline] = %w[nomodeset]
 default[:hardware][:sensors] = {}
+default[:hardware][:hwmon] = {}
+default[:hardware][:ipmi][:excluded_sensors] = []
 
 if node[:dmi] && node[:dmi][:system]
   case node[:dmi][:system][:manufacturer]
@@ -38,7 +40,7 @@ elsif node[:kernel][:modules].include?("i6300esb")
   default[:hardware][:watchdog] = "none"
 end
 
-if File.exist?("sys/devices/system/cpu/cpu0/cpufreq/scaling_governor") &&
+if File.exist?("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor") &&
    File.read("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor").chomp == "ondemand"
   default[:sysfs][:cpufreq_ondemand][:comment] = "Tune the ondemand CPU frequency governor"
   default[:sysfs][:cpufreq_ondemand][:parameters][:"devices/system/cpu/cpufreq/ondemand/up_threshold"] = "25"
index b632a23d93aeca70395fba08666ba87b27ab7827..35dd20ed892a9a55a7e223493ec07e752bfe0203 100644 (file)
@@ -7,8 +7,10 @@ description       "Configures hardware"
 version           "1.0.0"
 supports          "ubuntu"
 depends           "apt"
+depends           "chef"
 depends           "git"
 depends           "munin"
+depends           "prometheus"
 depends           "ohai"
 depends           "tools"
 depends           "sysfs"
index 454386459ce800658b4cd5fe571fdc8214ed4354..ebdf64bb116c09b790f10c44c46bba62990b4d9e 100644 (file)
 # limitations under the License.
 #
 
-include_recipe "tools"
+include_recipe "apt"
+include_recipe "git"
 include_recipe "munin"
+include_recipe "prometheus"
+include_recipe "sysfs"
+include_recipe "tools"
 
 ohai_plugin "hardware" do
   template "ohai.rb.erb"
@@ -47,7 +51,7 @@ end
 
 units = []
 
-if node[:roles].include?("bytemark") || node[:roles].include?("exonetric")
+if node[:roles].include?("bytemark") || node[:roles].include?("exonetric") || node[:roles].include?("prgmr")
   units << "0"
 end
 
@@ -83,14 +87,29 @@ when "TYAN"
 when "TYAN Computer Corporation"
   units << "0"
 when "Supermicro"
-  case product
-  when "H8DGU", "X9SCD", "X7DBU", "X7DW3", "X9DR7/E-(J)LN4F", "X9DR3-F", "X9DRW", "SYS-1028U-TN10RT+", "SYS-2028U-TN24R4T+", "SYS-1029P-WTRT", "Super Server"
-    units << "1"
-  else
-    units << "0"
-  end
+  units << "1"
 when "IBM"
   units << "0"
+when "VMware, Inc."
+  package "open-vm-tools"
+
+  # Remove timeSync plugin completely
+  # https://github.com/vmware/open-vm-tools/issues/302
+  file "/usr/lib/open-vm-tools/plugins/vmsvc/libtimeSync.so" do
+    action :delete
+    notifies :restart, "service[open-vm-tools]"
+  end
+
+  # Attempt to tell Host we are not interested in timeSync
+  execute "vmware-toolbox-cmd-timesync-disable" do
+    command "/usr/bin/vmware-toolbox-cmd timesync disable"
+    ignore_failure true
+  end
+
+  service "open-vm-tools" do
+    action [:enable, :start]
+    supports :status => true, :restart => true
+  end
 end
 
 units.sort.uniq.each do |unit|
@@ -122,13 +141,14 @@ if File.exist?("/etc/default/grub")
   execute "update-grub" do
     action :nothing
     command "/usr/sbin/update-grub"
+    not_if { ENV["TEST_KITCHEN"] }
   end
 
   template "/etc/default/grub" do
     source "grub.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables :units => units, :entry => grub_entry
     notifies :run, "execute[update-grub]"
   end
@@ -145,7 +165,7 @@ template "/etc/initramfs-tools/conf.d/mdadm" do
   source "initramfs-mdadm.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :run, "execute[update-initramfs]"
 end
 
@@ -154,21 +174,29 @@ service "haveged" do
   action [:enable, :start]
 end
 
-package "ipmitool" if node[:kernel][:modules].include?("ipmi_si")
+if node[:kernel][:modules].include?("ipmi_si")
+  package "ipmitool"
+  package "freeipmi-tools"
 
-package "irqbalance"
+  template "/etc/prometheus/ipmi_local.yml" do
+    source "ipmi_local.yml.erb"
+    owner "root"
+    group "root"
+    mode "644"
+  end
 
-template "/etc/default/irqbalance" do
-  source "irqbalance.erb"
-  owner "root"
-  group "root"
-  mode 0o644
+  prometheus_exporter "ipmi" do
+    port 9290
+    options "--config.file=/etc/prometheus/ipmi_local.yml"
+    subscribes :restart, "template[/etc/prometheus/ipmi_local.yml]"
+  end
 end
 
+package "irqbalance"
+
 service "irqbalance" do
   action [:start, :enable]
   supports :status => false, :restart => true, :reload => false
-  subscribes :restart, "template[/etc/default/irqbalance]"
 end
 
 # Link Layer Discovery Protocol Daemon
@@ -181,42 +209,48 @@ end
 tools_packages = []
 status_packages = {}
 
-node[:kernel][:modules].each_key do |modname|
-  case modname
-  when "cciss"
-    tools_packages << "ssacli"
-    status_packages["cciss-vol-status"] ||= []
-  when "hpsa"
-    tools_packages << "ssacli"
-    status_packages["cciss-vol-status"] ||= []
-  when "mptsas"
-    tools_packages << "lsiutil"
-    status_packages["mpt-status"] ||= []
-  when "mpt2sas", "mpt3sas"
-    tools_packages << "sas2ircu"
-    status_packages["sas2ircu-status"] ||= []
-  when "megaraid_mm"
-    tools_packages << "megactl"
-    status_packages["megaraid-status"] ||= []
-  when "megaraid_sas"
-    tools_packages << "megacli"
-    status_packages["megaclisas-status"] ||= []
-  when "aacraid"
-    tools_packages << "arcconf"
-    status_packages["aacraid-status"] ||= []
-  when "arcmsr"
-    tools_packages << "areca"
+if node[:virtualization][:role] != "guest" ||
+   (node[:virtualization][:system] != "lxc" &&
+    node[:virtualization][:system] != "lxd" &&
+    node[:virtualization][:system] != "openvz")
+
+  node[:kernel][:modules].each_key do |modname|
+    case modname
+    when "cciss"
+      tools_packages << "ssacli"
+      status_packages["cciss-vol-status"] ||= []
+    when "hpsa"
+      tools_packages << "ssacli"
+      status_packages["cciss-vol-status"] ||= []
+    when "mptsas"
+      tools_packages << "lsiutil"
+      status_packages["mpt-status"] ||= []
+    when "mpt2sas", "mpt3sas"
+      tools_packages << "sas2ircu"
+      status_packages["sas2ircu-status"] ||= []
+    when "megaraid_mm"
+      tools_packages << "megactl"
+      status_packages["megaraid-status"] ||= []
+    when "megaraid_sas"
+      tools_packages << "megacli"
+      status_packages["megaclisas-status"] ||= []
+    when "aacraid"
+      tools_packages << "arcconf"
+      status_packages["aacraid-status"] ||= []
+    when "arcmsr"
+      tools_packages << "areca"
+    end
   end
-end
 
-node[:block_device].each do |name, attributes|
-  next unless attributes[:vendor] == "HP" && attributes[:model] == "LOGICAL VOLUME"
+  node[:block_device].each do |name, attributes|
+    next unless attributes[:vendor] == "HP" && attributes[:model] == "LOGICAL VOLUME"
 
-  if name =~ /^cciss!(c[0-9]+)d[0-9]+$/
-    status_packages["cciss-vol-status"] |= ["cciss/#{Regexp.last_match[1]}d0"]
-  else
-    Dir.glob("/sys/block/#{name}/device/scsi_generic/*").each do |sg|
-      status_packages["cciss-vol-status"] |= [File.basename(sg)]
+    if name =~ /^cciss!(c[0-9]+)d[0-9]+$/
+      status_packages["cciss-vol-status"] |= ["cciss/#{Regexp.last_match[1]}d0"]
+    else
+      Dir.glob("/sys/block/#{name}/device/scsi_generic/*").each do |sg|
+        status_packages["cciss-vol-status"] |= [File.basename(sg)]
+      end
     end
   end
 end
@@ -237,8 +271,10 @@ if tools_packages.include?("areca")
   git "/opt/areca" do
     action :sync
     repository "https://git.openstreetmap.org/private/areca.git"
+    depth 1
     user "root"
     group "root"
+    not_if { ENV["TEST_KITCHEN"] }
   end
 else
   directory "/opt/areca" do
@@ -252,7 +288,7 @@ if status_packages.include?("cciss-vol-status")
     source "cciss-vol-statusd.erb"
     owner "root"
     group "root"
-    mode 0o755
+    mode "755"
     notifies :restart, "service[cciss-vol-statusd]"
   end
 
@@ -265,6 +301,14 @@ if status_packages.include?("cciss-vol-status")
     no_new_privileges true
     notifies :restart, "service[cciss-vol-statusd]"
   end
+else
+  systemd_service "cciss-vol-statusd" do
+    action :delete
+  end
+
+  template "/usr/local/bin/cciss-vol-statusd" do
+    action :delete
+  end
 end
 
 %w[cciss-vol-status mpt-status sas2ircu-status megaraid-status megaclisas-status aacraid-status].each do |status_package|
@@ -275,7 +319,7 @@ end
       source "raid.default.erb"
       owner "root"
       group "root"
-      mode 0o644
+      mode "644"
       variables :devices => status_packages[status_package]
     end
 
@@ -301,38 +345,43 @@ disks = if node[:hardware][:disk]
           []
         end
 
-# intel_ssds = disks.select { |d| d[:vendor] == "INTEL" && d[:model] =~ /^SSD/ }
-#
-# nvmes = if node[:hardware][:pci]
-#           node[:hardware][:pci].values.select { |pci| pci[:driver] == "nvme" }
-#         else
-#           []
-#         end
-#
-# intel_nvmes = nvmes.select { |pci| pci[:vendor_name] == "Intel Corporation" }
-#
-# if !intel_ssds.empty? || !intel_nvmes.empty?
-#   package "unzip"
-#
-#   intel_ssd_tool_version = "3.0.21"
-#
-#   remote_file "#{Chef::Config[:file_cache_path]}/Intel_SSD_Data_Center_Tool_#{intel_ssd_tool_version}_Linux.zip" do
-#     source "https://downloadmirror.intel.com/29115/eng/Intel_SSD_Data_Center_Tool_#{intel_ssd_tool_version}_Linux.zip"
-#   end
-#
-#   execute "#{Chef::Config[:file_cache_path]}/Intel_SSD_Data_Center_Tool_#{intel_ssd_tool_version}_Linux.zip" do
-#     command "unzip Intel_SSD_Data_Center_Tool_#{intel_ssd_tool_version}_Linux.zip isdct_#{intel_ssd_tool_version}-1_amd64.deb"
-#     cwd Chef::Config[:file_cache_path]
-#     user "root"
-#     group "root"
-#     not_if { File.exist?("#{Chef::Config[:file_cache_path]}/isdct_#{intel_ssd_tool_version}-1_amd64.deb") }
-#   end
-#
-#   dpkg_package "isdct" do
-#     version "#{intel_ssd_tool_version}-1"
-#     source "#{Chef::Config[:file_cache_path]}/isdct_#{intel_ssd_tool_version}-1_amd64.deb"
-#   end
-# end
+intel_ssds = disks.select { |d| d[:vendor] == "INTEL" && d[:model] =~ /^SSD/ }
+
+nvmes = if node[:hardware][:pci]
+          node[:hardware][:pci].values.select { |pci| pci[:driver] == "nvme" }
+        else
+          []
+        end
+
+intel_nvmes = nvmes.select { |pci| pci[:vendor_name] == "Intel Corporation" }
+
+if !intel_ssds.empty? || !intel_nvmes.empty?
+  package "unzip"
+
+  intel_mas_tool_version = "1.6"
+  intel_mas_package_version = "#{intel_mas_tool_version}.122-0"
+
+  remote_file "#{Chef::Config[:file_cache_path]}/Intel_MAS_CLI_Tool_#{intel_mas_tool_version}_Linux.zip" do
+    source "https://downloadmirror.intel.com/30259/eng/Intel%C2%AE_MAS_CLI_Tool_Linux_#{intel_mas_tool_version}.zip"
+  end
+
+  execute "#{Chef::Config[:file_cache_path]}/Intel_MAS_CLI_Tool_#{intel_mas_tool_version}_Linux.zip" do
+    command "unzip Intel_MAS_CLI_Tool_#{intel_mas_tool_version}_Linux.zip intelmas_#{intel_mas_package_version}_amd64.deb"
+    cwd Chef::Config[:file_cache_path]
+    user "root"
+    group "root"
+    not_if { ::File.exist?("#{Chef::Config[:file_cache_path]}/intelmas_#{intel_mas_package_version}_amd64.deb") }
+  end
+
+  dpkg_package "intelmas" do
+    version "#{intel_mas_package_version}"
+    source "#{Chef::Config[:file_cache_path]}/intelmas_#{intel_mas_package_version}_amd64.deb"
+  end
+
+  dpkg_package "isdct" do
+    action :purge
+  end
+end
 
 disks = disks.map do |disk|
   next if disk[:state] == "spun_down" || %w[unconfigured failed].any?(disk[:status])
@@ -352,6 +401,13 @@ disks = disks.map do |disk|
       elsif smart =~ %r{^.*,(\d+)/(\d+)$}
         munin = "#{device}-#{Regexp.last_match(1)}:#{Regexp.last_match(2)}"
       end
+    elsif disk[:device]
+      device = disk[:device].sub("/dev/", "")
+      smart = disk[:smart_device]
+
+      if smart =~ /^.*,(\d+),(\d+),(\d+)$/
+        munin = "#{device}-#{Regexp.last_match(1)}:#{Regexp.last_match(2)}:#{Regexp.last_match(3)}"
+      end
     end
   elsif disk[:device] =~ %r{^/dev/(nvme\d+)n\d+$}
     device = Regexp.last_match(1)
@@ -376,18 +432,25 @@ disks = disks.compact.uniq
 if disks.count.positive?
   package "smartmontools"
 
+  template "/etc/cron.daily/update-smart-drivedb" do
+    source "update-smart-drivedb.erb"
+    owner "root"
+    group "root"
+    mode "755"
+  end
+
   template "/usr/local/bin/smartd-mailer" do
     source "smartd-mailer.erb"
     owner "root"
     group "root"
-    mode 0o755
+    mode "755"
   end
 
   template "/etc/smartd.conf" do
     source "smartd.conf.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables :disks => disks
   end
 
@@ -395,15 +458,27 @@ if disks.count.positive?
     source "smartmontools.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
   end
 
-  service "smartd" do
+  service "smartmontools" do
     action [:enable, :start]
     subscribes :reload, "template[/etc/smartd.conf]"
     subscribes :restart, "template[/etc/default/smartmontools]"
   end
 
+  template "/etc/prometheus/collectors/smart.devices" do
+    source "smart.devices.erb"
+    owner "root"
+    group "root"
+    mode "644"
+    variables :disks => disks
+  end
+
+  prometheus_collector "smart" do
+    interval "15m"
+  end
+
   # Don't try and do munin monitoring of disks behind
   # an Areca controller as they only allow one thing to
   # talk to the controller at a time and smartd will
@@ -455,7 +530,7 @@ if File.exist?("/etc/mdadm/mdadm.conf")
   file "/etc/mdadm/mdadm.conf" do
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     content mdadm_conf
   end
 
@@ -469,7 +544,7 @@ template "/etc/modules" do
   source "modules.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 service "kmod" do
@@ -484,7 +559,7 @@ if node[:hardware][:watchdog]
     source "watchdog.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables :module => node[:hardware][:watchdog]
   end
 
@@ -531,16 +606,24 @@ unless Dir.glob("/sys/class/hwmon/hwmon*").empty?
     source "sensors.conf.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     notifies :run, "execute[/etc/sensors.d/chef.conf]"
   end
 end
 
 if node[:hardware][:shm_size]
+  execute "remount-dev-shm" do
+    action :nothing
+    command "/bin/mount -o remount /dev/shm"
+    user "root"
+    group "root"
+  end
+
   mount "/dev/shm" do
-    action [:mount, :enable]
+    action :enable
     device "tmpfs"
     fstype "tmpfs"
     options "rw,nosuid,nodev,size=#{node[:hardware][:shm_size]}"
+    notifies :run, "execute[remount-dev-shm]"
   end
 end
diff --git a/cookbooks/hardware/templates/default/ipmi_local.yml.erb b/cookbooks/hardware/templates/default/ipmi_local.yml.erb
new file mode 100644 (file)
index 0000000..4250a62
--- /dev/null
@@ -0,0 +1,13 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+modules:
+  default:
+    collectors:
+      - bmc
+      - ipmi
+      - dcmi
+      - chassis
+    exclude_sensor_ids:
+<% node[:hardware][:ipmi][:excluded_sensors].each do |sensor| -%>
+      - <%= sensor %>
+<% end -%>
diff --git a/cookbooks/hardware/templates/default/irqbalance.erb b/cookbooks/hardware/templates/default/irqbalance.erb
deleted file mode 100644 (file)
index 4a10bd2..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-# Configuration for the irqbalance daemon
-
-# Should irqbalance be enabled?
-ENABLED="1"
-# Balance the IRQs only once?
-ONESHOT="0"
-
-# irqbalance maintainer recommends ignore hint policy
-# http://sourceforge.net/p/e1000/bugs/394/?page=1
-DOPTIONS="--hintpolicy=ignore"
index 82194acf29769c5cbd7405c81c4d8107505e5898..c3308eb8cda835dee2faa652409126fc1ed4fd23 100644 (file)
@@ -287,7 +287,7 @@ Ohai.plugin(:Hardware) do
     disk = nil
 
     IO.popen(%w(ssacli controller all show config detail)).each do |line|
-      if line =~ /^Smart Array (\S+) /
+      if line =~ /^Smart (?:Array|HBA) (\S+) /
         controller = {
           :id => devices[:controllers].count,
           :model => Regexp.last_match(1),
@@ -303,6 +303,7 @@ Ohai.plugin(:Hardware) do
         disk = nil
       elsif controller && line =~ /^   (\S.*):\s+(.*)$/
         case Regexp.last_match(1)
+        when "Slot" then controller[:slot] = Regexp.last_match(2)
         when "Serial Number" then controller[:serial_number] = Regexp.last_match(2)
         when "Hardware Revision" then controller[:hardware_version] = Regexp.last_match(2)
         when "Firmware Version" then controller[:firmware_version] = Regexp.last_match(2)
@@ -320,15 +321,12 @@ Ohai.plugin(:Hardware) do
         controller[:arrays] << array[:id]
 
         disk = nil
-      elsif controller && line =~ /^      physicaldrive (\S+) /
-        disks << Regexp.last_match(1)
       elsif array && line =~ /^      physicaldrive (\S+)$/
         disk = {
           :id => devices[:disks].count,
           :controller => controller[:id],
           :arrays => [array[:id]],
-          :location => Regexp.last_match(1),
-          :smart_device => "cciss,#{disks.find_index(Regexp.last_match(1))}"
+          :location => Regexp.last_match(1)
         }
 
         devices[:disks] << disk
@@ -355,6 +353,14 @@ Ohai.plugin(:Hardware) do
     end
 
     controllers.each do |controller|
+      slot = controller[:slot]
+
+      IO.popen(%W(ssacli controller slot=#{slot} pd all show status)).each do |line|
+        if line =~ /^   physicaldrive (\S+) /
+          disks << Regexp.last_match(1)
+        end
+      end
+
       if device = Dir.glob("/sys/bus/pci/devices/#{controller[:pci_slot]}/cciss*").first
         controller[:device] = File.basename(device).sub(/^cciss(\d+)$/, "/dev/cciss/c\\1d0")
       elsif device = Dir.glob("/sys/bus/pci/devices/#{controller[:pci_slot]}/host*/target*:3:0/*:3:0:0/scsi_generic/sg*").first
@@ -363,6 +369,10 @@ Ohai.plugin(:Hardware) do
         controller[:device] = "/dev/#{File.basename(device)}"
       end
     end
+
+    devices[:disks].each do |disk|
+     disk[:smart_device] = "cciss,#{disks.find_index(disk[:location])}"
+    end
   end
 
   def find_megaraid_disks(devices)
@@ -766,10 +776,11 @@ Ohai.plugin(:Hardware) do
         array[:disks].map! do |location|
           disk = disks.find { |disk| disk[:location] == location }
 
+          controller_number = controller[:number] - 1
           device_number = disk[:device_number]
-          device = Dir.glob("#{host}/device/target*:1:#{device_number}/*:1:#{device_number}:0/scsi_generic/*").first
 
           disk[:device] = "/dev/#{File.basename(device)}"
+          disk[:smart_device] = "aacraid,#{controller_number},0,#{device_number}"
 
           disk[:arrays] << array[:id]
           disk[:id]
diff --git a/cookbooks/hardware/templates/default/smart.devices.erb b/cookbooks/hardware/templates/default/smart.devices.erb
new file mode 100644 (file)
index 0000000..36498d7
--- /dev/null
@@ -0,0 +1,9 @@
+<% @disks.each do |disk| -%>
+<% if disk[:smart] -%>
+/dev/<%= disk[:device] %>|<%= disk[:smart] %>
+<% elsif disk[:device] =~ /nvme/ -%>
+/dev/<%= disk[:device] %>|nvme
+<% else -%>
+/dev/<%= disk[:device] %>|sat
+<% end -%>
+<% end -%>
diff --git a/cookbooks/hardware/templates/default/update-smart-drivedb.erb b/cookbooks/hardware/templates/default/update-smart-drivedb.erb
new file mode 100644 (file)
index 0000000..5093be8
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+# DO NOT EDIT - This file is being maintained by Chef
+
+set -eu
+
+if [ -x /usr/sbin/update-smart-drivedb ]; then
+  /usr/sbin/update-smart-drivedb -u github > /dev/null
+fi
+
+exit 0
diff --git a/cookbooks/imagery/files/default/os-openmap-local-palette.txt b/cookbooks/imagery/files/default/os-openmap-local-palette.txt
new file mode 100644 (file)
index 0000000..deb8359
--- /dev/null
@@ -0,0 +1,256 @@
+0,0,0
+8,7,7
+24,24,24
+40,40,40
+52,52,52
+85,15,45
+49,83,63
+73,66,53
+61,61,72
+89,88,72
+80,80,80
+87,87,87
+112,83,88
+108,105,87
+87,88,104
+84,111,108
+100,100,100
+105,104,104
+120,120,118
+215,18,54
+148,105,35
+157,113,51
+216,120,19
+136,24,72
+189,38,104
+212,28,64
+216,47,79
+145,120,84
+142,96,102
+138,122,104
+138,120,120
+165,111,122
+217,69,74
+227,85,116
+63,143,54
+8,166,34
+0,166,41
+9,179,51
+55,148,82
+43,179,82
+76,132,88
+76,153,84
+97,170,90
+95,139,107
+121,159,121
+106,160,110
+124,184,117
+55,195,91
+54,200,88
+82,199,111
+152,152,8
+214,133,34
+225,151,59
+200,201,8
+243,243,0
+248,248,8
+174,140,87
+144,157,102
+136,136,120
+153,136,120
+136,158,120
+152,152,120
+162,136,104
+183,151,106
+187,184,104
+240,162,67
+201,155,102
+221,165,123
+226,173,102
+233,184,127
+146,204,109
+255,192,115
+248,200,120
+73,81,199
+255,60,140
+192,115,130
+235,101,128
+229,111,139
+0,159,184
+40,152,172
+69,135,144
+127,154,155
+92,167,180
+25,194,164
+120,214,142
+9,151,200
+0,154,207
+0,169,202
+14,170,200
+6,177,202
+24,161,216
+24,184,217
+45,168,210
+50,185,213
+0,191,230
+41,184,232
+75,184,213
+39,200,232
+81,201,215
+109,199,214
+115,216,212
+80,213,232
+85,216,248
+113,214,236
+117,232,248
+136,136,136
+153,136,136
+133,153,136
+152,152,136
+128,136,153
+152,136,152
+154,154,144
+152,152,152
+168,152,136
+185,150,136
+168,136,152
+185,135,153
+168,152,152
+184,152,152
+151,168,150
+157,191,153
+168,168,136
+184,168,136
+184,184,136
+168,168,152
+184,168,152
+184,184,152
+151,152,170
+171,152,171
+145,172,172
+167,167,167
+184,168,168
+168,188,168
+178,184,173
+184,184,168
+168,168,184
+185,167,184
+166,185,185
+183,184,183
+210,141,149
+255,135,158
+247,136,152
+200,168,132
+200,185,136
+216,191,128
+200,168,152
+199,184,152
+217,184,152
+210,145,169
+248,137,168
+232,154,167
+208,184,168
+242,166,184
+248,185,184
+141,193,137
+164,217,148
+189,220,165
+188,219,184
+158,225,175
+208,204,152
+242,200,145
+246,233,151
+200,200,168
+215,199,168
+216,216,168
+200,200,184
+216,200,184
+216,216,184
+232,200,168
+248,195,168
+232,216,168
+248,216,165
+232,200,184
+231,215,183
+248,216,184
+208,235,184
+232,232,168
+248,232,168
+228,248,168
+248,248,168
+232,232,184
+250,223,191
+252,225,189
+248,232,184
+232,248,184
+255,243,181
+247,247,184
+184,184,200
+248,182,201
+143,214,209
+181,207,204
+149,232,214
+179,232,204
+142,216,234
+169,216,226
+146,232,247
+176,232,242
+199,199,199
+216,200,200
+200,216,200
+216,216,200
+200,200,216
+217,200,216
+200,216,216
+216,216,216
+243,212,207
+200,232,200
+216,232,200
+200,248,200
+208,239,207
+209,241,205
+216,248,200
+200,232,216
+216,232,216
+200,248,216
+215,247,222
+216,247,216
+232,232,200
+251,232,201
+232,248,200
+248,248,200
+232,232,216
+248,232,216
+252,235,217
+232,248,216
+248,248,216
+216,216,232
+232,216,232
+247,215,229
+200,232,232
+216,232,232
+199,248,232
+216,248,232
+194,229,240
+200,232,248
+216,232,248
+199,248,248
+213,244,248
+212,244,250
+216,247,247
+230,235,228
+229,231,231
+232,232,232
+234,234,234
+248,232,232
+231,247,231
+247,247,232
+232,232,248
+248,232,248
+231,247,247
+252,252,252
+249,249,247
+254,254,254
+252,252,254
+255,255,255
+255,255,255
index 13a7f915b8e62d08c2fba5e7f0544beec879af5d..63b33b70fb39c041ef8e3f75ca791dd8416e74b5 100644 (file)
@@ -21,10 +21,8 @@ include_recipe "nginx"
 include_recipe "git"
 
 # Imagery gdal Requirements
-package %w[
-  gdal-bin
-  python-gdal
-]
+package "gdal-bin"
+# python-gdal - disable while broken in gis unstable repo
 
 # Imagery MapServer + Mapcache Requirements
 package %w[
@@ -51,26 +49,26 @@ package %w[
 directory "/srv/imagery/mapserver" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   recursive true
 end
 
 directory "/srv/imagery/common" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   recursive true
 end
 
 directory "/srv/imagery/common/ostn02-ntv2-data" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 remote_file "#{Chef::Config[:file_cache_path]}/ostn02-ntv2-data.zip" do
   source "https://www.ordnancesurvey.co.uk/docs/gps/ostn02-ntv2-data.zip"
-  not_if { File.exist?("/srv/imagery/common/ostn02-ntv2-data/OSTN02_NTv2.gsb") }
+  not_if { ::File.exist?("/srv/imagery/common/ostn02-ntv2-data/OSTN02_NTv2.gsb") }
 end
 
 execute "unzip-ostn02-ntv2-data" do
@@ -78,13 +76,12 @@ execute "unzip-ostn02-ntv2-data" do
   cwd "/srv/imagery/common/ostn02-ntv2-data"
   user "root"
   group "root"
-  not_if { File.exist?("/srv/imagery/common/ostn02-ntv2-data/OSTN02_NTv2.gsb") }
+  not_if { ::File.exist?("/srv/imagery/common/ostn02-ntv2-data/OSTN02_NTv2.gsb") }
 end
 
 nginx_site "default" do
   template "nginx_default.conf.erb"
   directory "/srv/imagery/default"
-  restart_nginx false
 end
 
 systemd_tmpfile "/run/mapserver-fastcgi" do
index 878ee0fe01ab59a9bd473597af9a29b2dc6d8a4c..b9af18645ff1fd4a7ef8f8b977926d519e36cb21 100644 (file)
@@ -26,6 +26,13 @@ cookbook_file "/srv/imagery/common/ossv-palette.txt" do
   mode "0644"
 end
 
+cookbook_file "/srv/imagery/common/os-openmap-local-palette.txt" do
+  source "os-openmap-local-palette.txt"
+  owner "root"
+  group "root"
+  mode "0644"
+end
+
 cookbook_file "/srv/imagery/common/osstvw_process" do
   source "osstvw_process"
   owner "root"
@@ -181,7 +188,6 @@ end
 imagery_layer "gb_os_sv_2016_04" do
   site "os.openstreetmap.org"
   title "April 2016"
-  default_layer true
   projection "EPSG:27700"
   source "/data/imagery/gb/os-sv/ossv-2016-04-combined.vrt"
   copyright "Contains Ordnance Survey data &copy; Crown copyright and database right 2016"
@@ -1049,3 +1055,76 @@ imagery_layer "gb_os_sv_diff_2015_11_2016_04" do
   url_aliases ["/sv-diff-2015-11-2016-04"]
   overlay true
 end
+
+imagery_layer "gb_os_om_local_2020_04" do
+  site "os.openstreetmap.org"
+  title "OS OpenMap Local - April 2020"
+  projection "EPSG:27700"
+  source "/data/imagery/gb/openmap-local/2020-04/os-openmap-local-2020-04-combined-sea-average-zstd22.vrt"
+  copyright "Contains OS data &copy; Crown copyright and database right 2020"
+  revision 2
+  background_colour "213 244 248" # OS OpenMap Local Water Blue
+  extension "os_om_local_png"
+  url_aliases ["/om-local-2020-04", "/om-local"]
+  default_layer true
+end
+
+imagery_layer "gb_os_om_local_2016_10" do
+  site "os.openstreetmap.org"
+  title "OS OpenMap Local - October 2016"
+  projection "EPSG:27700"
+  source "/data/imagery/gb/openmap-local/2016-10/os-openmap-local-2016-10.vrt"
+  copyright "Contains OS data &copy; Crown copyright and database right 2016"
+  background_colour "213 244 248" # OS OpenMap Local Water Blue
+  extension "os_om_local_png"
+end
+
+imagery_layer "gb_os_om_local_2017_04" do
+  site "os.openstreetmap.org"
+  title "OS OpenMap Local - April 2017"
+  projection "EPSG:27700"
+  source "/data/imagery/gb/openmap-local/2017-04/os-openmap-local-2017-04.vrt"
+  copyright "Contains OS data &copy; Crown copyright and database right 2017"
+  background_colour "213 244 248" # OS OpenMap Local Water Blue
+  extension "os_om_local_png"
+end
+
+imagery_layer "gb_os_om_local_2017_10" do
+  site "os.openstreetmap.org"
+  title "OS OpenMap Local - October 2017"
+  projection "EPSG:27700"
+  source "/data/imagery/gb/openmap-local/2017-10/os-openmap-local-2017-10.vrt"
+  copyright "Contains OS data &copy; Crown copyright and database right 2017"
+  background_colour "213 244 248" # OS OpenMap Local Water Blue
+  extension "os_om_local_png"
+end
+
+imagery_layer "gb_os_om_local_2018_04" do
+  site "os.openstreetmap.org"
+  title "OS OpenMap Local - April 2018"
+  projection "EPSG:27700"
+  source "/data/imagery/gb/openmap-local/2018-04/os-openmap-local-2018-04.vrt"
+  copyright "Contains OS data &copy; Crown copyright and database right 2018"
+  background_colour "213 244 248" # OS OpenMap Local Water Blue
+  extension "os_om_local_png"
+end
+
+imagery_layer "gb_os_om_local_2018_05" do
+  site "os.openstreetmap.org"
+  title "OS OpenMap Local - May 2018"
+  projection "EPSG:27700"
+  source "/data/imagery/gb/openmap-local/2018-05/os-openmap-local-2018-05.vrt"
+  copyright "Contains OS data &copy; Crown copyright and database right 2018"
+  background_colour "213 244 248" # OS OpenMap Local Water Blue
+  extension "os_om_local_png"
+end
+
+imagery_layer "gb_os_om_local_2019_04" do
+  site "os.openstreetmap.org"
+  title "OS OpenMap Local - April 2019"
+  projection "EPSG:27700"
+  source "/data/imagery/gb/openmap-local/2019-04/os-openmap-local-2019-04.vrt"
+  copyright "Contains OS data &copy; Crown copyright and database right 2019"
+  background_colour "213 244 248" # OS OpenMap Local Water Blue
+  extension "os_om_local_png"
+end
diff --git a/cookbooks/imagery/recipes/lu_lidar_hillshade.rb b/cookbooks/imagery/recipes/lu_lidar_hillshade.rb
new file mode 100644 (file)
index 0000000..c807429
--- /dev/null
@@ -0,0 +1,60 @@
+#
+# Cookbook:: imagery
+# Recipe:: lu_lidar_hillshade
+#
+# Copyright:: 2016, OpenStreetMap Foundation
+#
+# 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
+#
+#     https://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.
+#
+
+include_recipe "imagery"
+
+imagery_site "lidar-hillshade-2019.openstreetmap.lu" do
+  title "OpenStreetMap - Lidar Hillshade 2019"
+  bbox [[49.38, 5.64], [50.2, 6.64]]
+end
+
+# Delete borken layers like this
+
+imagery_layer "classy_mappers_delight_lidar_hillshade_2019" do
+  site "lidar-hillshade-2019.openstreetmap.lu"
+  action :delete
+end
+
+imagery_layer "mappers_delight_lidar_dem_2019" do
+  site "lidar-hillshade-2019.openstreetmap.lu"
+  projection "EPSG:3857"
+  source "/data/imagery/lu/lidar-hillshade/dem-3857.tif"
+  max_zoom 20
+  title "OpenStreetMap.lu Mapper's Delight 2019 Lidar DEM"
+  copyright 'Lidar data 2019 <a href="https://data.public.lu/fr/datasets/lidar-2019-releve-3d-du-territoire-luxembourgeois">Administration du Cadastre et de la Topographie Luxembourg</a>, DEM <a href="https://twitter.com/grischard">Guillaume Rischard</a>, CC0'
+end
+
+imagery_layer "mappers_delight_lidar_hillshade_2019_reprojected" do
+  site "lidar-hillshade-2019.openstreetmap.lu"
+  default_layer true
+  projection "EPSG:3857"
+  source "/data/imagery/lu/lidar-hillshade/lu_hillshade_2019-3857.tif"
+  max_zoom 20
+  title "OpenStreetMap.lu Mapper's Delight 2019 Lidar Hillshading"
+  copyright 'Lidar data 2019 <a href="https://data.public.lu/fr/datasets/lidar-2019-releve-3d-du-territoire-luxembourgeois">Administration du Cadastre et de la Topographie Luxembourg</a>, DEM and hillshading <a href="https://twitter.com/grischard">Guillaume Rischard</a>, CC0'
+end
+
+imagery_layer "mappers_delight_lidar_hillshade_2019_withunclassified" do
+  site "lidar-hillshade-2019.openstreetmap.lu"
+  projection "EPSG:3857"
+  source "/data/imagery/lu/lidar-hillshade/classy-hillshade.tif"
+  max_zoom 20
+  title "OpenStreetMap.lu Mapper's Delight 2019 Lidar Hillshading with unclassified points"
+  copyright 'Lidar data 2019 <a href="https://data.public.lu/fr/datasets/lidar-2019-releve-3d-du-territoire-luxembourgeois">Administration du Cadastre et de la Topographie Luxembourg</a>, DEM and hillshading <a href="https://twitter.com/grischard">Guillaume Rischard</a>, CC0'
+end
diff --git a/cookbooks/imagery/recipes/lu_ngl_dtm.rb b/cookbooks/imagery/recipes/lu_ngl_dtm.rb
new file mode 100644 (file)
index 0000000..528c408
--- /dev/null
@@ -0,0 +1,53 @@
+#
+# Cookbook:: imagery
+# Recipe:: lu_ngl_dtm
+#
+# Copyright:: 2016, OpenStreetMap Foundation
+#
+# 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
+#
+#     https://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.
+#
+
+include_recipe "imagery"
+
+imagery_site "ana-dtm-2017.openstreetmap.lu" do
+  title "OpenStreetMap - ANA DTM 2017"
+  bbox [[49.38, 5.64], [50.2, 6.64]]
+end
+
+imagery_layer "ana_dtm_2017" do
+  site "ana-dtm-2017.openstreetmap.lu"
+  projection "EPSG:3857"
+  source "/data/imagery/lu/LUREF_NGL/lu_color_relief-epsg3857-compress.tif"
+  max_zoom 21
+  title "DTM"
+  copyright '&copy; 2017 <a href="https://data.public.lu/fr/datasets/digital-terrain-model-high-dem-resolution/">Administration de la Navigation A&eacute;rienne Luxembourg</a>, CC0'
+end
+
+imagery_layer "ana_dtm_2017_hillshading" do
+  site "ana-dtm-2017.openstreetmap.lu"
+  projection "EPSG:3857"
+  source "/data/imagery/lu/LUREF_NGL/lu_hillshade_2017-epsg-3857-compress.tif"
+  max_zoom 21
+  title "DTM Hillshading (single light source)"
+  copyright '&copy; 2017 <a href="https://data.public.lu/fr/datasets/digital-terrain-model-high-dem-resolution/">Administration de la Navigation A&eacute;rienne Luxembourg</a>, CC0'
+end
+
+imagery_layer "ana_dtm_2017_hillshading_multi" do
+  site "ana-dtm-2017.openstreetmap.lu"
+  default_layer true
+  projection "EPSG:3857"
+  source "/data/imagery/lu/LUREF_NGL/ANA_LUREF_NGL_DTM_hillshade_multi_epsg3857.tif"
+  max_zoom 21
+  title "DTM Hillshading (multidirectional)"
+  copyright 'DEM 2017 <a href="https://data.public.lu/fr/datasets/digital-terrain-model-high-dem-resolution/">Administration de la Navigation A&eacute;rienne Luxembourg</a>, hillshading <a href="https://twitter.com/dmoraisferreira">David Morais Ferreira</a> &amp; <a href="https://twitter.com/grischard">Guillaume Rischard</a> CC0'
+end
index cddd9584760186c7629004ac3fc1dcc8d0178959..6affe4b80b06fe291e0450dcb9748660002f7cc9 100644 (file)
@@ -23,8 +23,8 @@ default_action :create
 
 property :layer, String, :name_property => true
 property :site, String, :required => true
-property :source, String, :required => true
-property :root_layer, [TrueClass, FalseClass], :default => false
+property :source, String, :required => [:create]
+property :root_layer, [true, false], :default => false
 property :title, String
 property :copyright, String, :default => "Copyright"
 property :projection, String, :default => "EPSG:3857"
@@ -37,14 +37,14 @@ property :extension, String, :default => "png"
 property :max_zoom, Integer, :default => 18
 property :url_aliases, [String, Array], :default => []
 property :revision, Integer, :default => 0
-property :overlay, [TrueClass, FalseClass], :default => false
-property :default_layer, [TrueClass, FalseClass], :default => false
+property :overlay, [true, false], :default => false
+property :default_layer, [true, false], :default => false
 
 action :create do
   file "/srv/imagery/layers/#{new_resource.site}/#{new_resource.layer}.yml" do
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     content YAML.dump(:name => new_resource.layer,
                       :title => new_resource.title || new_resource.layer,
                       :url => "//{s}.#{new_resource.site}/layer/#{new_resource.layer}/{z}/{x}/{y}.png",
@@ -59,24 +59,14 @@ action :create do
     source "mapserver.map.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables new_resource.to_hash
   end
 
-  # Disable legacy service
-  service "mapserv-fcgi-#{new_resource.layer}" do
-    action [:stop, :disable]
-  end
-
-  # Remove legacy service
-  systemd_service "mapserv-fcgi-#{new_resource.layer}" do
-    action :delete
-  end
-
   directory "/srv/imagery/nginx/#{new_resource.site}" do
     owner "root"
     group "root"
-    mode 0o755
+    mode "755"
     recursive true
   end
 
@@ -85,7 +75,7 @@ action :create do
     source "nginx_imagery_layer_fragment.conf.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables new_resource.to_hash
   end
 end
@@ -95,18 +85,10 @@ action :delete do
     action :delete
   end
 
-  service "mapserv-fcgi-layer-#{new_resource.layer}" do
-    action [:stop, :disable]
-  end
-
   file "/srv/imagery/mapserver/layer-#{new_resource.layer}.map" do
     action :delete
   end
 
-  systemd_service "mapserv-fcgi-#{new_resource.layer}" do
-    action :delete
-  end
-
   file "/srv/imagery/nginx/#{new_resource.site}/layer-#{new_resource.layer}.conf" do
     action :delete
   end
@@ -114,6 +96,5 @@ end
 
 def after_created
   notifies :create, "imagery_site[#{site}]"
-  notifies :reload, "service[nginx]"
-  # notifies :restart, "service[mapserv-fcgi-#{site}]"
+  notifies :restart, "service[nginx]"
 end
index d483803840e267a536e7526de694972b4c59aa0c..c30c26d9592d445ebfc733f9091ea31472bdee02 100644 (file)
@@ -22,28 +22,28 @@ require "yaml"
 default_action :create
 
 property :site, String, :name_property => true
-property :title, String, :required => true
+property :title, String, :required => [:create]
 property :aliases, [String, Array], :default => []
-property :bbox, Array, :required => true
+property :bbox, Array, :required => [:create]
 
 action :create do
   directory "/srv/#{new_resource.site}" do
     user "root"
     group "root"
-    mode 0o755
+    mode "755"
   end
 
   directory "/srv/imagery/layers/#{new_resource.site}" do
     user "root"
     group "root"
-    mode 0o755
+    mode "755"
     recursive true
   end
 
   directory "/srv/imagery/overlays/#{new_resource.site}" do
     user "root"
     group "root"
-    mode 0o755
+    mode "755"
     recursive true
   end
 
@@ -51,7 +51,7 @@ action :create do
     source "index.html.erb"
     user "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables :title => new_resource.title
   end
 
@@ -59,28 +59,28 @@ action :create do
     source "robots.txt"
     user "root"
     group "root"
-    mode 0o644
+    mode "644"
   end
 
   cookbook_file "/srv/#{new_resource.site}/imagery.css" do
     source "imagery.css"
     user "root"
     group "root"
-    mode 0o644
+    mode "644"
   end
 
   cookbook_file "/srv/#{new_resource.site}/clientaccesspolicy.xml" do
     source "clientaccesspolicy.xml"
     user "root"
     group "root"
-    mode 0o644
+    mode "644"
   end
 
   cookbook_file "/srv/#{new_resource.site}/crossdomain.xml" do
     source "crossdomain.xml"
     user "root"
     group "root"
-    mode 0o644
+    mode "644"
   end
 
   layers = Dir.glob("/srv/imagery/layers/#{new_resource.site}/*.yml").collect do |path|
@@ -91,7 +91,7 @@ action :create do
     source "imagery.js.erb"
     user "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables :bbox => new_resource.bbox, :layers => layers
   end
 
@@ -106,8 +106,9 @@ action :create do
                   "MS_ERRORFILE" => "stderr",
                   "GDAL_CACHEMAX" => "512"
       limit_nofile 16384
-      limit_cpu 60
-      memory_max "4G"
+      limit_cpu 180
+      memory_high "512M"
+      memory_max "1G"
       user "imagery"
       group "imagery"
       exec_start_pre "/bin/rm -f /run/mapserver-fastcgi/layer-#{new_resource.site}-#{index}.socket"
@@ -137,19 +138,20 @@ action :create do
   nginx_site new_resource.site do
     template "nginx_imagery.conf.erb"
     directory "/srv/imagery/#{new_resource.site}"
-    restart_nginx false
     variables new_resource.to_hash
   end
 end
 
 action :delete do
-  service "mapserv-fcgi-#{new_resource.site}" do
-    provider Chef::Provider::Service::Systemd
-    action [:stop, :disable]
-  end
+  %w[0 1 2 3 4 5 6 7].each do |index|
+    service "mapserv-fcgi-#{new_resource.site}-#{index}" do
+      provider Chef::Provider::Service::Systemd
+      action [:stop, :disable]
+    end
 
-  systemd_service "mapserv-fcgi-#{new_resource.site}" do
-    action :delete
+    systemd_service "mapserv-fcgi-#{new_resource.site}-#{index}" do
+      action :delete
+    end
   end
 
   nginx_site new_resource.site do
index 0f277444b45b0c9f23d16be14bb8718dfd22d394..bee7747abe4d3190a3ca033084cec4251c3cfc1b 100644 (file)
@@ -1,12 +1,14 @@
 function createMap(divName) {
   // Create a map
-  var map = L.map(divName).fitBounds(<%= @bbox.to_json %>);
+  var map = L.map(divName, {
+    worldCopyJump: true
+  }).fitBounds(<%= @bbox.to_json %>);
 
   // Create a layer switcher
   var layers = L.control.layers(null, null, {collapsed:false}).addTo(map);
 
   // Add OpenStreetMap layer
-  layers.addBaseLayer(L.tileLayer("//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
+  layers.addBaseLayer(L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
     attribution: "© <a target=\"_parent\" href=\"https://www.openstreetmap.org\">OpenStreetMap</a> and contributors, under an <a target=\"_parent\" href=\"https://www.openstreetmap.org/copyright\">open license</a>",
     maxZoom: 19
   }), "OpenStreetMap");
index 148543937426bc23543260f73e24e481a738ffdd..c6975cb788554cd988d1d8a31934880737a295d2 100644 (file)
@@ -4,11 +4,11 @@
     <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
     <title><%= @title %></title>
     <link rel="stylesheet" href="imagery.css" type="text/css" media="all" />
-    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin="anonymous"/>
-    <script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js" integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og==" crossorigin="anonymous"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-plugins/3.1.0/control/Permalink.min.js" integrity="sha256-gz/xcf8U9RgwWUhQK8SgCuS024ACmdXf+eWrglT2KDE=" crossorigin="anonymous"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-plugins/3.1.0/control/Permalink.Layer.min.js" integrity="sha256-IR3dLMDgW61PPbrjYPe8eD7ou3RBAaVyoD4CNcq+8tw=" crossorigin="anonymous"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-plugins/3.1.0/control/Permalink.Overlay.min.js" integrity="sha256-xoP/txAKIYDr3MjZh1f2qtNn8lEa6zmhhkPxoejGgQM=" crossorigin="anonymous"></script>
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.6.0/leaflet.css" integrity="sha256-SHMGCYmST46SoyGgo4YR/9AlK1vf3ff84Aq9yK4hdqM=" crossorigin="anonymous" />
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.6.0/leaflet.js" integrity="sha256-fNoRrwkP2GuYPbNSJmMJOCyfRB2DhPQe0rGTgzRsyso=" crossorigin="anonymous"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-plugins/3.3.1/control/Permalink.min.js" integrity="sha256-gz/xcf8U9RgwWUhQK8SgCuS024ACmdXf+eWrglT2KDE=" crossorigin="anonymous"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-plugins/3.3.1/control/Permalink.Layer.min.js" integrity="sha256-IR3dLMDgW61PPbrjYPe8eD7ou3RBAaVyoD4CNcq+8tw=" crossorigin="anonymous"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-plugins/3.3.1/control/Permalink.Overlay.min.js" integrity="sha256-xoP/txAKIYDr3MjZh1f2qtNn8lEa6zmhhkPxoejGgQM=" crossorigin="anonymous"></script>
     <script type="text/javascript" src="imagery.js"></script>
     <style type="text/css">
     @media print {
index 4bec1334f2a8dd9830f24aabbd6a1ae63647266b..1f918d0f8f8023a75a5e163b1a1dc4cff5476c3a 100644 (file)
@@ -7,7 +7,7 @@ MAP
     MIMETYPE "image/png"
     IMAGEMODE RGB
     EXTENSION "png"
-    FORMATOPTION "COMPRESSION=9"
+    FORMATOPTION "COMPRESSION=6"
     FORMATOPTION "PALETTE_FORCE=on"
     FORMATOPTION "PALETTE=/srv/imagery/common/ossv-palette.txt"
   END
@@ -19,7 +19,19 @@ MAP
     MIMETYPE "image/png"
     IMAGEMODE RGBA
     EXTENSION "png"
-    FORMATOPTION "COMPRESSION=9"
+    FORMATOPTION "COMPRESSION=6"
+  END
+<% end -%>
+<% if @extension == "os_om_local_png" -%>
+  OUTPUTFORMAT
+    NAME "os_om_local_png"
+    DRIVER AGG/PNG
+    MIMETYPE "image/png"
+    IMAGEMODE RGB
+    EXTENSION "png"
+    FORMATOPTION "COMPRESSION=6"
+    FORMATOPTION "PALETTE_FORCE=on"
+    FORMATOPTION "PALETTE=/srv/imagery/common/os-openmap-local-palette.txt"
   END
 <% end -%>
 
index 3d9a5bf5cde9cbbc1613222df9b56dc6a82937d8..51670c71514eb2bdd996259980df7bbc62a7577b 100644 (file)
@@ -1,6 +1,6 @@
 server {
-    listen 80 deferred backlog=16384 reuseport fastopen=2048 default_server;
-    listen 443 ssl deferred backlog=16384 reuseport fastopen=2048 http2; # No default_server here unless certificate specified here too.
+    listen 80 deferred backlog=16384 reuseport default_server;
+    listen 443 ssl deferred backlog=16384 reuseport http2; # No default_server here unless certificate specified here too.
 
     server_name  _;
     default_type text/html;
index dcdc2872961f2cbe6c0e4832dc8941aebb0be049..b038071b7861dbd4f8a840c18ec62f7ea8567025 100644 (file)
@@ -21,7 +21,7 @@ upstream <%= @name %>_fastcgi {
 }
 
 server {
-    listen 443 ssl;
+    listen 443 ssl http2;
     server_name <%= @name %> a.<%= @name %> b.<%= @name %> c.<%= @name %><% @aliases.each do |alias_name| %> <%= alias_name %> a.<%= alias_name %> b.<%= alias_name %> c.<%= alias_name %><%- end -%>;
 
     ssl_certificate /etc/ssl/certs/<%= @name %>.pem;
@@ -45,9 +45,6 @@ server {
     gzip_comp_level 9;
     gzip_vary on;
 
-    sendfile   on;
-    tcp_nopush on;
-
     # Include site imagery layers
     include /srv/imagery/nginx/<%= @name %>/layer-*.conf;
 }
index 856ec6765f07a4fd89a1e3f5a5b293673b3d0e45..372bf0e561a21413107c584904a33a0c48aa2423 100644 (file)
@@ -4,6 +4,7 @@ location ~* "^/layer/<%= @layer %>/(\d+)/(\d+)/(\d+)\.(png|jpg|jpeg)$" {
   fastcgi_param QUERY_STRING "map=/srv/imagery/mapserver/layer-<%= @layer %>.map&mode=tile&layers=<%= @layer %>&tilemode=gmap&tile=$2+$3+$1";
   fastcgi_pass "<%= @site %>_fastcgi";
   fastcgi_buffers 8 64k;
+  fastcgi_busy_buffers_size 64k;
   include fastcgi_params;
   fastcgi_param REQUEST_METHOD "GET";
   fastcgi_param HTTP_PROXY "";
@@ -16,10 +17,16 @@ location ~* "^/layer/<%= @layer %>/(\d+)/(\d+)/(\d+)\.(png|jpg|jpeg)$" {
   # Free connection to socket for other requests
   fastcgi_keep_conn off;
 
-  fastcgi_cache_lock on;
-  fastcgi_cache_lock_timeout 30s;
   fastcgi_cache_valid 200 21d;
+
+  # Serve stale cache on errors or if updating
   fastcgi_cache_use_stale error timeout updating http_500 http_503;
+  # If in cache as stale, serve stale and update in background
+  fastcgi_cache_background_update on;
+  # Enable revalidation using If-Modified-Since and If-None-Match for stale items
+  fastcgi_cache_revalidate on;
+
+  keepalive_requests 0;
 
   # Ignore client abort as it causes issues with the pipeline
   fastcgi_ignore_client_abort on;
@@ -34,6 +41,8 @@ location ~* "^/layer/<%= @layer %>/(\d+)/(\d+)/(\d+)\.(png|jpg|jpeg)$" {
 
   # Add HTTP Cache-Control + Expires Headers
   expires 7d;
+  add_header Cache-Control "stale-while-revalidate=604800, stale-if-error=604800";
+  add_header x-cache-status $upstream_cache_status;
 
   # Allow CORS requests
   add_header 'Access-Control-Allow-Origin' '*';
index f7d44a45e8949e1c35a84ffbeed5550621f19f15..4c785d15e093224b4e9297a09171de74a8610af5 100644 (file)
@@ -41,7 +41,7 @@ incrontabs.each do |user, lines|
   file "/var/spool/incron/#{user}" do
     owner user
     group "incron"
-    mode 0o600
+    mode "600"
     content lines.join("\n")
   end
 end
diff --git a/cookbooks/irc/README.md b/cookbooks/irc/README.md
new file mode 100644 (file)
index 0000000..051982f
--- /dev/null
@@ -0,0 +1,3 @@
+# Irc Cookbook
+
+This cookbook installs and configures the irc.openstreetmap.org web site.
diff --git a/cookbooks/irc/files/default/html/index.html b/cookbooks/irc/files/default/html/index.html
new file mode 100644 (file)
index 0000000..21e5668
--- /dev/null
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>irc.openstreetmap.org</title>
+    <link rel="stylesheet" href="style.css" />
+  </head>
+  <body>
+    <h1>irc.openstreetmap.org</h1>
+    <div>
+      <form method="get" action="https://webchat.oftc.net/">
+        <table>
+          <tr>
+            <th>Nickname</th>
+            <td><input name="nick" type="text" /></td>
+          </tr>
+          <tr>
+            <th>Channel</th>
+            <td>
+              <select name="channels">
+                <option value="#osm">#osm</option>
+                <option value="#osm-dev">#osm-dev</option>
+                <option value="#osm-ewg">#osm-ewg</option>
+                <option value="#osm-cwg">#osm-cwg</option>
+                <option value="#osm-ar">#osm-ar</option>
+                <option value="#osm-asia">#osm-asia</option>
+                <option value="#osm-au">#osm-au</option>
+                <option value="#osm-br">#osm-br</option>
+                <option value="#osm-bw">#osm-bw</option>
+                <option value="#osm-by">#osm-by</option>
+                <option value="#osm-ca">#osm-ca</option>
+                <option value="#osm-ch">#osm-ch</option>
+                <option value="#osm-cz">#osm-cz</option>
+                <option value="#osm-de">#osm-de</option>
+                <option value="#osm-dk">#osm-dk</option>
+                <option value="#osm-es">#osm-es</option>
+                <option value="#osm-fi">#osm-fi</option>
+                <option value="#osm-fr">#osm-fr</option>
+                <option value="#osm-gb">#osm-gb</option>
+                <option value="#osm-gr">#osm-gr</option>
+                <option value="#osm-gsoc">#osm-gsoc</option>
+                <option value="#osm-ht">#osm-ht</option>
+                <option value="#osm-ie">#osm-ie</option>
+                <option value="#osm-it">#osm-it</option>
+                <option value="#osm-ke">#osm-ke</option>
+                <option value="#osm-latam">#osm-latam</option>
+                <option value="#osm-local">#osm-local</option>
+                <option value="#osm-lv">#osm-lv</option>
+                <option value="#osm-nl">#osm-nl</option>
+                <option value="#osm-no">#osm-no</option>
+                <option value="#osm-nominatim">#osm-nominatim</option>
+                <option value="#osm-pl">#osm-pl</option>
+                <option value="#osm-pt">#osm-pt</option>
+                <option value="#osm-ru">#osm-ru</option>
+                <option value="#osm.se">#osm.se</option>
+                <option value="#osm-strategic">#osm-strategic</option>
+                <option value="#osm-ua">#osm-ua</option>
+                <option value="#osm-us">#osm-us</option>
+                <option value="#osm-za">#osm-za</option>
+                <option value="#osm-zh">#osm-zh</option>
+                <option value="#osmf-gm">#osmf-gm</option>
+                <option value="#osrm">#osrm</option>
+                <option value="#openrailwaymap">#openrailwaymap</option>
+                <option value="#hot">#hot</option>
+              </select>
+            </td>
+          </tr>
+          <tr>
+            <th></th>
+            <td><input type="submit" value="Connect" /></td>
+          </tr>
+        </table>
+      </form>
+    </div>
+  </body>
+</html>
diff --git a/cookbooks/irc/files/default/html/style.css b/cookbooks/irc/files/default/html/style.css
new file mode 100644 (file)
index 0000000..3a8dc02
--- /dev/null
@@ -0,0 +1,11 @@
+h1 {
+  text-align: center;
+}
+
+div {
+  display: flex;
+}
+
+form {
+  margin: auto;
+}
similarity index 72%
rename from cookbooks/cgiirc/metadata.rb
rename to cookbooks/irc/metadata.rb
index 3b4b8207171a401ec66b0e8ea592af207e52ca81..6e745f6e6c2ef9c399190f602a6eb66f3486fe61 100644 (file)
@@ -1,8 +1,8 @@
-name              "cgiirc"
+name              "irc"
 maintainer        "OpenStreetMap Administrators"
 maintainer_email  "admins@openstreetmap.org"
 license           "Apache-2.0"
-description       "Installs and configures cgiirc"
+description       "Configures irc.openstreetmap.org"
 
 version           "1.0.0"
 supports          "ubuntu"
similarity index 77%
rename from cookbooks/cgiirc/recipes/default.rb
rename to cookbooks/irc/recipes/default.rb
index 4e8a9c1cc934da05de1dacbcd7a35cb81075257f..7fbc7ff743d77754a8f405de5d5fa1d8b936aba8 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Cookbook:: cgiirc
+# Cookbook:: irc
 # Recipe:: default
 #
 # Copyright:: 2011, OpenStreetMap Foundation
 
 include_recipe "apache"
 
-blocks = data_bag_item("cgiirc", "blocks")
-
-package "cgiirc"
+ssl_certificate "irc.openstreetmap.org" do
+  domains ["irc.openstreetmap.org", "irc.osm.org"]
+  notifies :reload, "service[apache2]"
+end
 
-template "/etc/cgiirc/cgiirc.config" do
-  source "cgiirc.config.erb"
+directory "/srv/irc.openstreetmap.org" do
   owner "root"
   group "root"
-  mode 0o644
+  mode "755"
 end
 
-template "/etc/cgiirc/ipaccess" do
-  source "ipaccess.erb"
+remote_directory "/srv/irc.openstreetmap.org/html" do
+  source "html"
   owner "root"
   group "root"
-  mode 0o644
-  variables :blocks => blocks["addresses"]
-end
-
-ssl_certificate "irc.openstreetmap.org" do
-  domains ["irc.openstreetmap.org", "irc.osm.org"]
-  notifies :reload, "service[apache2]"
+  mode "755"
+  files_owner "root"
+  files_group "root"
+  files_mode "644"
 end
 
 apache_site "irc.openstreetmap.org" do
   template "apache.erb"
+  directory "/srv/irc.openstreetmap.org/html"
   variables :aliases => ["irc.osm.org"]
 end
similarity index 60%
rename from cookbooks/cgiirc/templates/default/apache.erb
rename to cookbooks/irc/templates/default/apache.erb
index 1afb107ba1d2326fb69417c46796741b5c40c58d..ceb112e184fbbee3f9e15fa693f47c9648a28d2f 100644 (file)
   CustomLog /var/log/apache2/<%= @name %>-access.log combined
   ErrorLog /var/log/apache2/<%= @name %>-error.log
 
-  DocumentRoot /usr/lib/cgi-bin/cgiirc
-  DirectoryIndex irc.cgi
-  Alias /images /usr/share/images/cgiirc
-
-  <Directory "/usr/lib/cgi-bin/cgiirc">
-    AddHandler cgi-script .cgi
-    Require all granted
-  </Directory>
-
-  <Directory "/usr/share/images/cgiirc">
-    Require all granted
-  </Directory>
-
-  <IfModule mod_deflate.c>
-    RemoveOutputFilter DEFLATE
-    SetEnv no-gzip
-  </IfModule>
+  DocumentRoot <%= @directory %>
 </VirtualHost>
 <% unless @aliases.empty? -%>
 
 <% @aliases.each do |alias_name| -%>
   ServerAlias <%= alias_name %>
 <% end -%>
-       ServerAdmin webmaster@openstreetmap.org
+  ServerAdmin webmaster@openstreetmap.org
 
-       CustomLog /var/log/apache2/<%= @name %>-access.log combined
-       ErrorLog /var/log/apache2/<%= @name %>-error.log
+  CustomLog /var/log/apache2/<%= @name %>-access.log combined
+  ErrorLog /var/log/apache2/<%= @name %>-error.log
 
-       RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
-       RedirectPermanent / https://<%= @name %>/
+  RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
+  RedirectPermanent / https://<%= @name %>/
 </VirtualHost>
+
+<Directory <%= @directory %>>
+  Require all granted
+</Directory>
index 46dda49ceb4c3410bde5960a0a915dc1fa162617..bb431975a25e25f1a51828f22779b874cec4dcf6 100644 (file)
@@ -1,2 +1,4 @@
 default[:kibana][:version] = "4.1.1"
 default[:kibana][:sites] = {}
+
+default[:accounts][:users][:kibana][:status] = :role
index 83c575e9bc058893ad6393eb95193ecf5f810e7b..ec3e6f4c60b80e857e15a8223ea04edfbd6eb743 100644 (file)
@@ -6,5 +6,6 @@ description       "Installs and configures a kibana server"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
 depends           "systemd"
index c2e2693b37948e9b614fad9af8c83ce2479044a7..1a8c7712a07eaab254c02343f891158661d3cb2b 100644 (file)
@@ -19,6 +19,7 @@
 
 require "yaml"
 
+include_recipe "accounts"
 include_recipe "apache"
 
 apache_module "proxy_http"
@@ -26,14 +27,14 @@ apache_module "proxy_http"
 version = node[:kibana][:version]
 
 remote_file "#{Chef::Config[:file_cache_path]}/kibana-#{version}.tar.gz" do
-  source "https://download.elastic.co/kibana/kibana/kibana-4.1.1-linux-x64.tar.gz"
-  not_if { File.exist?("/opt/kibana-#{version}/bin/kibana") }
+  source "https://download.elastic.co/kibana/kibana/kibana-#{version}-linux-x64.tar.gz"
+  not_if { ::File.exist?("/opt/kibana-#{version}/bin/kibana") }
 end
 
 directory "/opt/kibana-#{version}" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 execute "unzip-kibana-#{version}" do
@@ -41,25 +42,25 @@ execute "unzip-kibana-#{version}" do
   cwd "/opt/kibana-#{version}"
   user "root"
   group "root"
-  not_if { File.exist?("/opt/kibana-#{version}/bin/kibana") }
+  not_if { ::File.exist?("/opt/kibana-#{version}/bin/kibana") }
 end
 
 directory "/etc/kibana" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 directory "/var/run/kibana" do
   owner "kibana"
   group "kibana"
-  mode 0o755
+  mode "755"
 end
 
 directory "/var/log/kibana" do
   owner "kibana"
   group "kibana"
-  mode 0o755
+  mode "755"
 end
 
 systemd_service "kibana@" do
@@ -86,7 +87,7 @@ node[:kibana][:sites].each do |name, details|
                       ))
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     notifies :restart, "service[kibana@#{name}]"
   end
 
diff --git a/cookbooks/letsencrypt/attributes/default.rb b/cookbooks/letsencrypt/attributes/default.rb
new file mode 100644 (file)
index 0000000..21b32a8
--- /dev/null
@@ -0,0 +1 @@
+default[:accounts][:users][:letsencrypt][:status] = :role
index 73bd8a658c1731a2f15b835ddb2f9ef4e4b1050b..f24681589e13687c2c16e0fc79804ec9e7aa6391 100755 (executable)
@@ -2,6 +2,7 @@
 
 require "socket"
 require "openssl"
+require "net/http"
 
 host = ARGV.shift
 address = ARGV.shift
@@ -23,6 +24,8 @@ end
 
 if ssl
   certificate = ssl.peer_cert
+  chain = ssl.peer_cert_chain.drop(1)
+  issuer = chain.first
 
   if Time.now < certificate.not_before
     puts "Certificate #{domains.first} on #{host} not valid until #{certificate.not_before}"
@@ -30,6 +33,43 @@ if ssl
     puts "Certificate #{domains.first} on #{host} expires at #{certificate.not_after}"
   end
 
+  digest = OpenSSL::Digest::SHA1.new
+  certificate_id = OpenSSL::OCSP::CertificateId.new(certificate, issuer, digest)
+  ocsp_request = OpenSSL::OCSP::Request.new.add_certid(certificate_id)
+
+  authority_info_access = certificate.extensions.find { |ext| ext.oid == "authorityInfoAccess" }
+  ocsp = authority_info_access.value.split("\n").find { |desc| desc.start_with?("OCSP") }
+  ocsp_uri = URI(ocsp.sub(/^.* URI:/, ""))
+
+  http_response = Net::HTTP.start(ocsp_uri.hostname, ocsp_uri.port) do |http|
+    path = ocsp_uri.path
+    path = "/" if path.empty?
+    http.post(path, ocsp_request.to_der, "Content-Type" => "application/ocsp-request")
+  end
+
+  basic_response = OpenSSL::OCSP::Response.new(http_response.body).basic
+
+  store = OpenSSL::X509::Store.new
+  store.set_default_paths
+
+  unless basic_response.verify(chain, store)
+    raise "OCSP response is not signed by a trusted certificate"
+  end
+
+  single_response = basic_response.find_response(certificate_id)
+
+  unless single_response
+    raise "OCSP response does not have the status for the certificate"
+  end
+
+  unless single_response.check_validity
+    raise "OCSP response is not valid"
+  end
+
+  if single_response.cert_status == OpenSSL::OCSP::V_CERTSTATUS_REVOKED
+    puts "Certificate #{domains.first} on #{host} has been revoked"
+  end
+
   subject_alt_name = certificate.extensions.find { |ext| ext.oid == "subjectAltName" }
 
   if subject_alt_name.nil?
index 6a04821852ed1f195cb509dcc6440e9ca1bc11ed..2b7e6b4a8278c77eaa9ddb7bef35141a90853e24 100755 (executable)
@@ -4,6 +4,7 @@ cd /srv/acme.openstreetmap.org
 
 /usr/bin/certbot renew \
     --quiet \
+    --preferred-chain "DST Root CA X3" \
     --config-dir /srv/acme.openstreetmap.org/config \
     --work-dir /srv/acme.openstreetmap.org/work \
     --logs-dir /srv/acme.openstreetmap.org/logs \
index 3af7bdd2e99fc3815a355dbe31cd1367afb885a2..50f1874b2d5a973d14f466186325a2d5d34cda8c 100644 (file)
@@ -6,4 +6,5 @@ description       "Support for letsencrypt certificates"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
index 42d1e4678c859faf609ecc0682f725797c2baa5e..c41732cf64bf28db7815c6a16b1cee68703aa325 100644 (file)
@@ -17,6 +17,7 @@
 # limitations under the License.
 #
 
+include_recipe "accounts"
 include_recipe "apache"
 
 keys = data_bag_item("chef", "keys")
@@ -29,31 +30,31 @@ package %w[
 directory "/etc/letsencrypt" do
   owner "letsencrypt"
   group "letsencrypt"
-  mode 0o755
+  mode "755"
 end
 
 directory "/var/lib/letsencrypt" do
   owner "letsencrypt"
   group "letsencrypt"
-  mode 0o755
+  mode "755"
 end
 
 directory "/var/log/letsencrypt" do
   owner "letsencrypt"
   group "letsencrypt"
-  mode 0o700
+  mode "700"
 end
 
 directory "/srv/acme.openstreetmap.org" do
   owner "letsencrypt"
   group "letsencrypt"
-  mode 0o755
+  mode "755"
 end
 
 directory "/srv/acme.openstreetmap.org/html" do
   owner "letsencrypt"
   group "letsencrypt"
-  mode 0o755
+  mode "755"
 end
 
 ssl_certificate "acme.openstreetmap.org" do
@@ -69,55 +70,55 @@ end
 directory "/srv/acme.openstreetmap.org/config" do
   owner "letsencrypt"
   group "letsencrypt"
-  mode 0o755
+  mode "755"
 end
 
 directory "/srv/acme.openstreetmap.org/work" do
   owner "letsencrypt"
   group "letsencrypt"
-  mode 0o755
+  mode "755"
 end
 
 directory "/srv/acme.openstreetmap.org/logs" do
   owner "letsencrypt"
   group "letsencrypt"
-  mode 0o700
+  mode "700"
 end
 
 directory "/srv/acme.openstreetmap.org/.chef" do
   owner "letsencrypt"
   group "letsencrypt"
-  mode 0o2775
+  mode "2775"
 end
 
 file "/srv/acme.openstreetmap.org/.chef/client.pem" do
   content keys["letsencrypt"].join("\n")
   owner "letsencrypt"
   group "letsencrypt"
-  mode 0o660
+  mode "660"
 end
 
 cookbook_file "/srv/acme.openstreetmap.org/.chef/knife.rb" do
   source "knife.rb"
   owner "letsencrypt"
   group "letsencrypt"
-  mode 0o660
+  mode "660"
 end
 
 remote_directory "/srv/acme.openstreetmap.org/bin" do
   source "bin"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   files_owner "root"
   files_group "root"
-  files_mode 0o755
+  files_mode "755"
 end
 
 directory "/srv/acme.openstreetmap.org/requests" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 certificates = search(:node, "letsencrypt:certificates").each_with_object({}) do |n, c|
@@ -136,7 +137,7 @@ certificates.each do |name, details|
     source "request.erb"
     owner "root"
     group "letsencrypt"
-    mode 0o754
+    mode "754"
     variables details
   end
 
@@ -147,10 +148,11 @@ certificates.each do |name, details|
     user "letsencrypt"
     group "letsencrypt"
     subscribes :run, "template[/srv/acme.openstreetmap.org/requests/#{name}]"
+    not_if { ENV["TEST_KITCHEN"] }
   end
 end
 
-Dir.each_child("/srv/acme.openstreetmap.org/requests") do |name|
+Dir.glob("*", :base => "/srv/acme.openstreetmap.org/requests") do |name|
   next if certificates.include?(name)
 
   file "/srv/acme.openstreetmap.org/requests/#{name}" do
@@ -169,13 +171,29 @@ template "/srv/acme.openstreetmap.org/bin/check-certificates" do
   source "check-certificates.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   variables :certificates => certificates
 end
 
-template "/etc/cron.d/letsencrypt" do
-  source "cron.erb"
+cron_d "letencrypt-renew" do
+  minute "00"
+  hour "*/12"
+  user "letsencrypt"
+  command "/srv/acme.openstreetmap.org/bin/renew"
+  mailto "admins@openstreetmap.org"
+end
+
+cron_d "letencrypt-check" do
+  minute "30"
+  hour "*/12"
+  user "letsencrypt"
+  command "/srv/acme.openstreetmap.org/bin/check-certificates"
+  mailto "admins@openstreetmap.org"
+end
+
+template "/etc/logrotate.d/letsencrypt" do
+  source "logrotate.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
diff --git a/cookbooks/letsencrypt/templates/default/cron.erb b/cookbooks/letsencrypt/templates/default/cron.erb
deleted file mode 100644 (file)
index 74a8ee0..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-
-MAILTO=admins@openstreetmap.org
-
-00 */12 * * * letsencrypt /srv/acme.openstreetmap.org/bin/renew
-30 */12 * * * letsencrypt /srv/acme.openstreetmap.org/bin/check-certificates
diff --git a/cookbooks/letsencrypt/templates/default/logrotate.erb b/cookbooks/letsencrypt/templates/default/logrotate.erb
new file mode 100644 (file)
index 0000000..57fe6d6
--- /dev/null
@@ -0,0 +1,6 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+/srv/acme.openstreetmap.org/logs/*.log {
+    missingok
+    compress
+}
index eaefa5bbe1bf08ef1816aed5440ba453ababd882..365b315a7cfe52cd926c4a3030dd7324d86207e6 100644 (file)
@@ -4,6 +4,7 @@
 
 /usr/bin/certbot certonly \
     --non-interactive \
+    --preferred-chain "DST Root CA X3" \
     --config-dir /srv/acme.openstreetmap.org/config \
     --work-dir /srv/acme.openstreetmap.org/work \
     --logs-dir /srv/acme.openstreetmap.org/logs \
index 4014b7207bc99a5e8e53f917901b44b3ffe5befa..ff9cace3ef453fc814b8fd12b9fdbf3d7e719708 100644 (file)
@@ -2,3 +2,5 @@ default[:logstash][:forwarder]["output.logstash"]["hosts"] = ["logstash.openstre
 default[:logstash][:forwarder]["output.logstash"]["ssl.certificate_authorities"] = "/etc/filebeat/filebeat.crt"
 default[:logstash][:forwarder]["output.logstash"]["ssl.verification_mode"] = "none"
 default[:logstash][:forwarder]["filebeat.prospectors"] = []
+
+default[:elasticsearch][:cluster][:name] = "logstash"
index e13ece1b0ebca6e6ccbfbbc8f8f2d5dcb3ee97e5..a1a7d387bc4385f451f2f29c107816480fc25608 100644 (file)
@@ -6,4 +6,6 @@ description       "Installs and configures a elasticsearch server"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "apt"
+depends           "elasticsearch"
 depends           "networking"
index babff56df277c1532a6249251a4fad18b68d59aa..712b33cb8154da1ec7a7be73140db605d57e4f87 100644 (file)
@@ -17,6 +17,7 @@
 # limitations under the License.
 #
 
+include_recipe "elasticsearch"
 include_recipe "networking"
 
 keys = data_bag_item("logstash", "keys")
@@ -30,7 +31,7 @@ cookbook_file "/var/lib/logstash/beats.crt" do
   source "beats.crt"
   user "root"
   group "logstash"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[logstash]"
 end
 
@@ -38,7 +39,7 @@ file "/var/lib/logstash/beats.key" do
   content keys["beats"].join("\n")
   user "root"
   group "logstash"
-  mode 0o640
+  mode "640"
   notifies :restart, "service[logstash]"
 end
 
@@ -46,32 +47,31 @@ template "/etc/logstash/conf.d/chef.conf" do
   source "logstash.conf.erb"
   user "root"
   group "root"
-  mode 0o644
-  notifies :reload, "service[logstash]"
+  mode "644"
+  notifies :start, "service[logstash]"
 end
 
 file "/etc/logrotate.d/logstash" do
-  mode 0o644
+  mode "644"
 end
 
 template "/etc/default/logstash" do
   source "logstash.default.erb"
   user "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[logstash]"
 end
 
 service "logstash" do
   action [:enable, :start]
-  supports :status => true, :restart => true, :reload => true
 end
 
 template "/etc/cron.daily/expire-logstash" do
   source "expire.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 forwarders = search(:node, "recipes:logstash\\:\\:forwarder")
index 14866558b3fc40e27d33d1b11d2aba7ab8eeacb2..af74c9e4cf5fb2aca52e1ef4937c3592427560a8 100644 (file)
 
 require "yaml"
 
+include_recipe "apt"
+
 package "filebeat"
 
 cookbook_file "/etc/filebeat/filebeat.crt" do
   source "beats.crt"
   user "root"
   group "root"
-  mode 0o600
+  mode "600"
   notifies :restart, "service[filebeat]"
 end
 
@@ -33,7 +35,7 @@ file "/etc/filebeat/filebeat.yml" do
   content YAML.dump(node[:logstash][:forwarder].to_hash)
   user "root"
   group "root"
-  mode 0o600
+  mode "600"
   notifies :restart, "service[filebeat]"
 end
 
index dc12f2ffa69916d0b540cb7cd955dd2d8fd874c6..db8f66c693bc1ee6d181419cb2df119359b31166 100644 (file)
@@ -7,3 +7,4 @@ description       "Installs and configures mailman"
 version           "1.0.0"
 supports          "ubuntu"
 depends           "apache"
+depends           "chef"
index 6e53ee8e531a17fb080a287d65fc716944600477..2525f9c0440cd5aa45420883be2818b2a2304a1f 100644 (file)
@@ -21,18 +21,29 @@ require "securerandom"
 
 include_recipe "apache"
 
-package "mailman"
+package %w[
+  locales-all
+  mailman
+]
 
-node.normal_unless[:mailman][:subscribe_form_secret] = SecureRandom.base64(48)
+subscribe_form_secret = persistent_token("mailman", "subscribe_form_secret")
 
 template "/etc/mailman/mm_cfg.py" do
   source "mm_cfg.py.erb"
   user "root"
   group "root"
-  mode 0o644
+  mode "644"
+  variables :subscribe_form_secret => subscribe_form_secret
   notifies :restart, "service[mailman]"
 end
 
+execute "newlist" do
+  command "newlist -q mailman mailman@example.com mailman"
+  user "root"
+  group "root"
+  not_if { ::File.exist?("/var/lib/mailman/lists/mailman/") }
+end
+
 service "mailman" do
   action [:enable, :start]
   supports :restart => true, :reload => true
@@ -56,5 +67,5 @@ template "/etc/cron.daily/lists-backup" do
   source "backup.cron.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
index 12a550c03a36695ef18482fb13f9a3fbd334d464..a876ae81edd5747c4eeb473b64ffbafd7b4c8cb0 100644 (file)
@@ -9,10 +9,9 @@ B=lists-$D.tar.gz
 mkdir $T/lists-$D
 ln -s /var/lib/mailman $T/lists-$D/mailman
 
-export GZIP="--rsyncable -9"
 export RSYNC_RSH="ssh -ax"
 
-nice tar --create --gzip --dereference --directory=$T --file=$T/$B lists-$D
+nice tar --create --dereference --warning=no-file-changed --directory=$T lists-$D | nice gzip --rsyncable -9 > $T/$B
 nice rsync --preallocate --fuzzy $T/$B backup::backup
 
 rm -rf $T
index 5252157f27e4e952eefaf9a8a8662b7a8d1f16bd..53b4990d45caf2914e66f5b2acb0d560467b2d3f 100644 (file)
@@ -109,7 +109,7 @@ POSTFIX_STYLE_VIRTUAL_DOMAINS = ['openstreetmap.org']
 
 #-------------------------------------------------------------
 # Secret for web forms to protect against XSRF attacks
-SUBSCRIBE_FORM_SECRET='<%= node[:mailman][:subscribe_form_secret] %>'
+SUBSCRIBE_FORM_SECRET='<%= @subscribe_form_secret %>'
 
 # Note - if you're looking for something that is imported from mm_cfg, but you
 # didn't find it above, it's probably in /usr/lib/mailman/Mailman/Defaults.py.
index 59838f9206df8dbd529d19798c47816d977ce825..221a4eb9a3fb0d65a0c57f202b67cf4f4a55af44 100644 (file)
@@ -4,9 +4,6 @@ default[:apt][:sources] = node[:apt][:sources] | ["mediawiki"]
 # Default to enabling the "wiki" role
 default[:accounts][:users][:wiki][:status] = :role
 
-# Use prefork as PHP is to dumb for anything else
-default[:apache][:mpm] = "prefork"
-
 # Set mediawiki defaults
 default[:mediawiki][:user] = "wiki"
 default[:mediawiki][:group] = "wiki"
index 9df8048079287980de97d44bb3500bac0428839e..6bc4c0ee6aa8cba7fe0b64502e1e5881c0e73d8c 100644 (file)
@@ -6,7 +6,11 @@ description       "Installs and configures mediawiki"
 
 version           "1.0.0"
 supports          "ubuntu"
-depends           "memcached"
+depends           "accounts"
 depends           "apache"
-depends           "mysql"
+depends           "apt"
+depends           "chef"
 depends           "git"
+depends           "memcached"
+depends           "mysql"
+depends           "php"
index 27c7cb48fe1b228a4b076345c67b78774fbb2c5a..fc61a22368f6ede6a97fd9dbc2b36027a36f3c16 100644 (file)
 # limitations under the License.
 #
 
-include_recipe "memcached"
+include_recipe "accounts"
 include_recipe "apache"
-include_recipe "mysql"
+include_recipe "apt"
 include_recipe "git"
+include_recipe "memcached"
+include_recipe "mysql"
+include_recipe "php::fpm"
 
 # Mediawiki Base Requirements
 package %w[
-  php
   php-cli
   php-curl
   php-gd
@@ -34,6 +36,7 @@ package %w[
   php-xml
   php-zip
   composer
+  unzip
 ]
 
 # Mediawiki enhanced difference engine
@@ -64,17 +67,23 @@ package %w[
 ]
 
 # Mediawiki packages for SyntaxHighight support
-package "python-pygments"
+package "python3-pygments"
 
 file "/etc/mediawiki/parsoid/settings.js" do
   action :delete
 end
 
 template "/etc/mediawiki/parsoid/config.yaml" do
+  action :nothing
   source "parsoid-config.yaml.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
+end
+
+notify_group "parsoid-config" do
+  action :run
+  notifies :create, "template[/etc/mediawiki/parsoid/config.yaml]"
 end
 
 service "parsoid" do
@@ -84,10 +93,10 @@ service "parsoid" do
   subscribes :restart, "template[/etc/mediawiki/parsoid/config.yaml]"
 end
 
-apache_module "php7.2"
-
-link "/etc/php/7.2/apache2/conf.d/20-wikidiff2.ini" do
+link "/etc/php/#{node[:php][:version]}/fpm/conf.d/20-wikidiff2.ini" do
   to "../../mods-available/wikidiff2.ini"
 end
 
+apache_module "proxy"
+apache_module "proxy_fcgi"
 apache_module "rewrite"
index 1fe4faea5ec657c3a3ae46765e369d4bdf6dba2b..9f477a53f695a66c8423f1c6d563f2263d3c1d43 100644 (file)
@@ -19,7 +19,7 @@
 
 default_action :create
 
-property :extension, :kind_of => String, :name_attribute => true
+property :extension, :kind_of => String, :name_property => true
 property :site, :kind_of => String, :required => true
 property :source, :kind_of => String
 property :template, :kind_of => String
@@ -38,10 +38,10 @@ action :create do
       source new_resource.source
       owner node[:mediawiki][:user]
       group node[:mediawiki][:group]
-      mode 0o755
+      mode "755"
       files_owner node[:mediawiki][:user]
       files_group node[:mediawiki][:group]
-      files_mode 0o755
+      files_mode "755"
     end
   else
     extension_repository = new_resource.repository || default_repository
@@ -57,10 +57,11 @@ action :create do
       action :sync
       repository extension_repository
       reference extension_reference
+      depth 1
       enable_submodules true
       user node[:mediawiki][:user]
       group node[:mediawiki][:group]
-      ignore_failure extension_repository.start_with?("git://github.com/wikimedia/mediawiki-extensions")
+      ignore_failure extension_repository.start_with?("https://github.com/wikimedia/mediawiki-extensions")
     end
   end
 
@@ -70,7 +71,7 @@ action :create do
       source new_resource.template
       user node[:mediawiki][:user]
       group node[:mediawiki][:group]
-      mode 0o664
+      mode "664"
       variables new_resource.variables
     end
   else
@@ -78,7 +79,7 @@ action :create do
       content "<?php wfLoadExtension( '#{new_resource.extension}' );\n"
       user node[:mediawiki][:user]
       group node[:mediawiki][:group]
-      mode 0o664
+      mode "664"
     end
   end
 
@@ -88,6 +89,7 @@ action :create do
     cwd mediawiki_directory
     user node[:mediawiki][:user]
     group node[:mediawiki][:group]
+    environment "COMPOSER_HOME" => site_directory
     only_if { ::File.exist?("#{extension_directory}/composer.json") }
     subscribes :run, "git[#{extension_directory}]"
   end
@@ -122,7 +124,7 @@ action_class do
   end
 
   def default_repository
-    "git://github.com/wikimedia/mediawiki-extensions-#{new_resource.extension}.git"
+    "https://github.com/wikimedia/mediawiki-extensions-#{new_resource.extension}.git"
   end
 end
 
index a3862ca521c8c50810e4e6b16f57887c42818a2f..d3fd852eef860ee2979b34aff5a10b3aba579b6f 100644 (file)
 
 default_action :create
 
-property :site, :kind_of => String, :name_attribute => true
+property :site, :kind_of => String, :name_property => true
 property :aliases, :kind_of => [String, Array]
 property :directory, :kind_of => String
-property :version, :kind_of => String, :default => "1.33"
+property :version, :kind_of => String, :default => "1.35"
 property :database_name, :kind_of => String, :required => true
-property :database_user, :kind_of => String, :required => true
-property :database_password, :kind_of => String, :required => true
+property :database_user, :kind_of => String, :required => [:create, :update]
+property :database_password, :kind_of => String, :required => [:create, :update]
 property :sitename, :kind_of => String, :default => "OpenStreetMap Wiki"
 property :metanamespace, :kind_of => String, :default => "OpenStreetMap"
 property :logo, :kind_of => String, :default => "$wgStylePath/common/images/wiki.png"
@@ -37,21 +37,27 @@ property :skin, :kind_of => String, :default => "vector"
 property :site_notice, :kind_of => [String, TrueClass, FalseClass], :default => false
 property :site_readonly, :kind_of => [String, TrueClass, FalseClass], :default => false
 property :admin_user, :kind_of => String, :default => "Admin"
-property :admin_password, :kind_of => String, :required => true
+property :admin_password, :kind_of => String, :required => [:create]
 property :private_accounts, :kind_of => [TrueClass, FalseClass], :default => false
 property :private_site, :kind_of => [TrueClass, FalseClass], :default => false
 property :recaptcha_public_key, :kind_of => String
 property :recaptcha_private_key, :kind_of => String
 property :extra_file_extensions, :kind_of => [String, Array], :default => []
+property :fpm_max_children, :kind_of => Integer, :default => 5
+property :fpm_start_servers, :kind_of => Integer, :default => 2
+property :fpm_min_spare_servers, :kind_of => Integer, :default => 1
+property :fpm_max_spare_servers, :kind_of => Integer, :default => 3
+property :fpm_request_terminate_timeout, :kind_of => Integer, :default => 300
+property :fpm_prometheus_port, :kind_of => Integer
 property :reload_apache, :kind_of => [TrueClass, FalseClass], :default => true
 
 action :create do
-  node.normal_unless[:mediawiki][:sites][new_resource.site] = {}
+  node.default[:mediawiki][:sites][new_resource.site] = {
+    :directory => site_directory,
+    :version => new_resource.version
+  }
 
-  node.normal[:mediawiki][:sites][new_resource.site][:directory] = site_directory
-  node.normal[:mediawiki][:sites][new_resource.site][:version] = new_resource.version
-
-  node.normal_unless[:mediawiki][:sites][new_resource.site][:wgSecretKey] = SecureRandom.base64(48)
+  secret_key = persistent_token("mediawiki", new_resource.site, "wgSecretKey")
 
   mysql_user "#{new_resource.database_user}@localhost" do
     password new_resource.database_password
@@ -94,21 +100,20 @@ action :create do
   declare_resource :directory, site_directory do
     owner node[:mediawiki][:user]
     group node[:mediawiki][:group]
-    mode 0o775
+    mode "775"
   end
 
   declare_resource :directory, mediawiki_directory do
     owner node[:mediawiki][:user]
     group node[:mediawiki][:group]
-    mode 0o775
+    mode "775"
   end
 
-  mediawiki_reference = "REL#{new_resource.version}".tr(".", "_")
-
   git mediawiki_directory do
     action :sync
-    repository "https://gerrit.wikimedia.org/r/p/mediawiki/core.git"
+    repository "https://gerrit.wikimedia.org/r/mediawiki/core.git"
     revision mediawiki_reference
+    depth 1
     user node[:mediawiki][:user]
     group node[:mediawiki][:group]
     notifies :run, "execute[#{mediawiki_directory}/composer.json]", :immediately
@@ -122,6 +127,7 @@ action :create do
     cwd mediawiki_directory
     user node[:mediawiki][:user]
     group node[:mediawiki][:group]
+    environment "COMPOSER_HOME" => site_directory
   end
 
   template "#{mediawiki_directory}/composer.local.json" do
@@ -129,7 +135,7 @@ action :create do
     source "composer.local.json.erb"
     owner node[:mediawiki][:user]
     group node[:mediawiki][:group]
-    mode 0o664
+    mode "664"
   end
 
   # Safety catch if git doesn't update but install.php hasn't run
@@ -146,19 +152,19 @@ action :create do
   declare_resource :directory, "#{mediawiki_directory}/images" do
     owner "www-data"
     group node[:mediawiki][:group]
-    mode 0o775
+    mode "775"
   end
 
   declare_resource :directory, "#{mediawiki_directory}/cache" do
     owner "www-data"
     group node[:mediawiki][:group]
-    mode 0o775
+    mode "775"
   end
 
   declare_resource :directory, "#{mediawiki_directory}/LocalSettings.d" do
     user node[:mediawiki][:user]
     group node[:mediawiki][:group]
-    mode 0o775
+    mode "775"
   end
 
   template "#{mediawiki_directory}/LocalSettings.php" do
@@ -166,22 +172,59 @@ action :create do
     source "LocalSettings.php.erb"
     owner node[:mediawiki][:user]
     group node[:mediawiki][:group]
-    mode 0o664
+    mode "664"
     variables :name => new_resource.site,
               :directory => mediawiki_directory,
               :database_params => database_params,
-              :mediawiki => mediawiki_params
+              :mediawiki => mediawiki_params,
+              :secret_key => secret_key
     notifies :run, "execute[#{mediawiki_directory}/maintenance/update.php]"
   end
 
-  template "/etc/cron.d/mediawiki-#{cron_name}" do
-    cookbook "mediawiki"
-    source "mediawiki.cron.erb"
-    owner "root"
-    group "root"
-    mode 0o644
-    variables :name => new_resource.site, :directory => site_directory,
-              :user => node[:mediawiki][:user]
+  cron_d "mediawiki-#{cron_name}-sitemap" do
+    comment "Generate sitemap.xml daily"
+    minute "30"
+    hour "0"
+    user node[:mediawiki][:user]
+    command "/usr/bin/nice /usr/bin/php -d memory_limit=2048M -d error_reporting=22517 #{site_directory}/w/maintenance/generateSitemap.php --server=https://#{new_resource.site} --urlpath=https://#{new_resource.site}/ --fspath=#{site_directory} --quiet --skip-redirects"
+  end
+
+  cron_d "mediawiki-#{cron_name}-jobs" do
+    comment "Run mediawiki jobs"
+    minute "*/3"
+    user node[:mediawiki][:user]
+    command "/usr/bin/nice /usr/bin/php -d memory_limit=2048M -d error_reporting=22517 #{site_directory}/w/maintenance/runJobs.php --server=https://#{new_resource.site} --maxtime=160 --memory-limit=2048M --procs=8 --quiet"
+  end
+
+  cron_d "mediawiki-#{cron_name}-email-jobs" do
+    comment "Run mediawiki email jobs"
+    user node[:mediawiki][:user]
+    command "/usr/bin/nice /usr/bin/php -d memory_limit=2048M -d error_reporting=22517 #{site_directory}/w/maintenance/runJobs.php --server=https://#{new_resource.site} --maxtime=30 --type=enotifNotify --memory-limit=2048M --procs=4 --quiet"
+  end
+
+  cron_d "mediawiki-#{cron_name}-refresh-links" do
+    comment "Run mediawiki refresh links table weekly"
+    minute "5"
+    hour "0"
+    weekday "0"
+    user node[:mediawiki][:user]
+    command "/usr/bin/nice /usr/bin/php -d memory_limit=2048M -d error_reporting=22517 #{site_directory}/w/maintenance/refreshLinks.php --server=https://#{new_resource.site} --memory-limit=2048M --quiet"
+  end
+
+  cron_d "mediawiki-#{cron_name}-cleanup-gs" do
+    comment "Clean up imagemagick garbage"
+    minute "10"
+    hour "2"
+    user node[:mediawiki][:user]
+    command "/usr/bin/find /tmp/ -maxdepth 1 -type f -user www-data -mmin +90 -name 'gs_*' -delete"
+  end
+
+  cron_d "mediawiki-#{cron_name}-cleanup-magick" do
+    comment "Clean up imagemagick garbage"
+    minute "20"
+    hour "2"
+    user node[:mediawiki][:user]
+    command "/usr/bin/find /tmp/ -maxdepth 1 -type f -user www-data -mmin +90 -name 'magick-*' -delete"
   end
 
   template "/etc/cron.daily/mediawiki-#{cron_name}-backup" do
@@ -189,7 +232,7 @@ action :create do
     source "mediawiki-backup.cron.erb"
     owner "root"
     group "root"
-    mode 0o700
+    mode "700"
     variables :name => new_resource.site,
               :directory => site_directory,
               :database_params => database_params
@@ -359,16 +402,6 @@ action :create do
     update_site false
   end
 
-  # LocalisationUpdate Update Cron
-  # template "/etc/cron.d/mediawiki-#{name}-LocalisationUpdate" do
-  #   cookbook "mediawiki"
-  #   source "mediawiki-LocalisationUpdate.cron.erb"
-  #   owner "root"
-  #   group "root"
-  #   mode 0755
-  #   variables :name => name, :directory => site_directory, :user => node[:mediawiki][:user]
-  # end
-
   # mediawiki_extension "Translate" do
   #   site new_resource.site
   #   template "mw-ext-Translate.inc.php.erb"
@@ -418,7 +451,14 @@ action :create do
   mediawiki_extension "osmtaginfo" do
     site new_resource.site
     template "mw-ext-osmtaginfo.inc.php.erb"
-    repository "git://github.com/Firefishy/osmtaginfo.git"
+    repository "https://github.com/Firefishy/osmtaginfo.git"
+    tag "live"
+    update_site false
+  end
+
+  mediawiki_extension "OSMCALWikiWidget" do
+    site new_resource.site
+    repository "https://github.com/thomersch/OSMCALWikiWidget.git"
     tag "live"
     update_site false
   end
@@ -426,17 +466,15 @@ action :create do
   mediawiki_extension "SimpleMap" do
     site new_resource.site
     template "mw-ext-SimpleMap.inc.php.erb"
-    repository "git://github.com/Firefishy/SimpleMap.git"
+    repository "https://github.com/Firefishy/SimpleMap.git"
     tag "live"
     update_site false
   end
 
   mediawiki_extension "SlippyMap" do
     site new_resource.site
-    template "mw-ext-SlippyMap.inc.php.erb"
-    repository "git://github.com/Firefishy/SlippyMap.git"
-    tag "live"
     update_site false
+    action :delete
   end
 
   mediawiki_extension "Mantle" do
@@ -466,7 +504,7 @@ action :create do
     cookbook "mediawiki"
     owner node[:mediawiki][:user]
     group node[:mediawiki][:group]
-    mode 0o644
+    mode "644"
     backup false
   end
 
@@ -474,7 +512,7 @@ action :create do
     cookbook "mediawiki"
     owner node[:mediawiki][:user]
     group node[:mediawiki][:group]
-    mode 0o644
+    mode "644"
     backup false
   end
 
@@ -482,7 +520,7 @@ action :create do
     cookbook "mediawiki"
     owner node[:mediawiki][:user]
     group node[:mediawiki][:group]
-    mode 0o644
+    mode "644"
     backup false
   end
 
@@ -490,6 +528,20 @@ action :create do
     domains [new_resource.site] + Array(new_resource.aliases)
   end
 
+  php_fpm new_resource.site do
+    pm_max_children new_resource.fpm_max_children
+    pm_start_servers new_resource.fpm_start_servers
+    pm_min_spare_servers new_resource.fpm_min_spare_servers
+    pm_max_spare_servers new_resource.fpm_max_spare_servers
+    request_terminate_timeout new_resource.fpm_request_terminate_timeout
+    php_admin_values "open_basedir" => "#{site_directory}/:/usr/share/php/:/dev/null:/tmp/"
+    php_values "memory_limit" => "500M",
+               "max_execution_time" => "240",
+               "upload_max_filesize" => "70M",
+               "post_max_size" => "100M"
+    prometheus_port new_resource.fpm_prometheus_port
+  end
+
   apache_site new_resource.site do
     cookbook "mediawiki"
     template "apache.erb"
@@ -517,7 +569,7 @@ action :update do
     source "LocalSettings.php.erb"
     owner node[:mediawiki][:user]
     group node[:mediawiki][:group]
-    mode 0o664
+    mode "664"
     variables :name => new_resource.site,
               :directory => mediawiki_directory,
               :database_params => database_params,
@@ -555,10 +607,23 @@ action :delete do
 end
 
 action_class do
+  include Chef::Mixin::PersistentToken
+
   def site_directory
     new_resource.directory || "/srv/#{new_resource.site}"
   end
 
+  def mediawiki_reference
+    shell_out!("git", "ls-remote", "--refs", "--sort=-version:refname",
+               "https://gerrit.wikimedia.org/r/mediawiki/core.git",
+               "refs/tags/#{new_resource.version}.*")
+      .stdout
+      .split("\n")
+      .first
+      .split("/")
+      .last
+  end
+
   def cron_name
     new_resource.site.tr(".", "_")
   end
index adcc2ae87accb3b668be37fc5b35c63b85667e26..f70ad6afeb029f28f879c94c100502236fcd7257 100644 (file)
@@ -19,7 +19,7 @@
 
 default_action :create
 
-property :skin, :kind_of => String, :name_attribute => true
+property :skin, :kind_of => String, :name_property => true
 property :site, :kind_of => String, :required => true
 property :source, :kind_of => String
 property :template, :kind_of => String
@@ -37,10 +37,10 @@ action :create do
       source new_resource.source
       owner node[:mediawiki][:user]
       group node[:mediawiki][:group]
-      mode 0o755
+      mode "755"
       files_owner node[:mediawiki][:user]
       files_group node[:mediawiki][:group]
-      files_mode 0o755
+      files_mode "755"
     end
   else
     skin_repository = new_resource.repository || default_repository
@@ -53,7 +53,7 @@ action :create do
       enable_submodules true
       user node[:mediawiki][:user]
       group node[:mediawiki][:group]
-      ignore_failure skin_repository.start_with?("git://github.com/wikimedia/mediawiki-skins")
+      ignore_failure skin_repository.start_with?("https://github.com/wikimedia/mediawiki-skins")
     end
   end
 
@@ -63,7 +63,7 @@ action :create do
       source new_resource.template
       user node[:mediawiki][:user]
       group node[:mediawiki][:group]
-      mode 0o664
+      mode "664"
       variables new_resource.variables
     end
   else
@@ -79,7 +79,7 @@ action :create do
       content file_content
       user node[:mediawiki][:user]
       group node[:mediawiki][:group]
-      mode 0o664
+      mode "664"
       only_if { ::File.exist?(skin_file) }
     end
   end
@@ -114,7 +114,7 @@ action_class do
   end
 
   def default_repository
-    "git://github.com/wikimedia/mediawiki-skins-#{new_resource.skin}.git"
+    "https://github.com/wikimedia/mediawiki-skins-#{new_resource.skin}.git"
   end
 end
 
index ac9625580a1e5998bdefacf4b081195d07a5443d..f3c127e5af2663e0d31d388c67650fa3f8c91bb9 100644 (file)
@@ -46,6 +46,7 @@ $wgEnableUserEmail  = true; # UPO
 $wgEmergencyContact = "<%= @mediawiki[:email_contact] %>";
 $wgPasswordSender   = "<%= @mediawiki[:email_sender] %>";
 $wgPasswordSenderName = "<%= @mediawiki[:email_sender_name] %>"; //Replaced by MediaWiki:Emailsender in v1.23.0
+$wgNoReplyAddress = "<%= @mediawiki[:email_sender] %>";
 
 $wgEnotifUserTalk      = true; # UPO
 $wgEnotifWatchlist     = true; # UPO
@@ -141,7 +142,7 @@ $wgLanguageCode = "en";
 $wgPageLanguageUseDB = true;
 $wgGroupPermissions['user']['pagelang'] = true;
 
-$wgSecretKey = '<%= @node[:mediawiki][:sites][@name][:wgSecretKey] %>';
+$wgSecretKey = '<%= @secret_key %>';
 
 # Site upgrade key. Must be set to a string (default provided) to turn on the
 # web installer while LocalSettings.php is in place
@@ -229,12 +230,19 @@ $wgGroupPermissions['*']['createaccount'] = false;
 $wgUploadPath = "$wgScriptPath/img_auth.php";
 <% end -%>
 
+<% if not(@mediawiki[:private_accounts]) and not(@mediawiki[:private_site]) -%>
+# user group "confirmed" with identical rights as "autoconfirmed", but assigned manually by sysops
+$wgGroupPermissions['confirmed'] = $wgGroupPermissions['autoconfirmed'];
+$wgAddGroups['sysop'][] = 'confirmed';
+$wgRemoveGroups['sysop'][] = 'confirmed';
+<% end -%>
+
 # Allow Subpages on Main Namespace
 $wgNamespacesWithSubpages[NS_MAIN] = true;
 
 # DNS Blacklists to use
 $wgEnableDnsBlacklist = true;
-$wgDnsBlacklistUrls = array( 'proxies.dnsbl.sorbs.net.', 'opm.tornevall.org.', 'xbl.spamhaus.org.', 'dnsbl-3.uceprotect.net.' );
+$wgDnsBlacklistUrls = array( 'proxies.dnsbl.sorbs.net.', 'opm.tornevall.org.', 'xbl.spamhaus.org.', 'dnsbl-2.uceprotect.net.' );
 
 # Require validated email to edit
 $wgEmailConfirmToEdit = true;
@@ -266,7 +274,8 @@ $wgAllowExternalImagesFrom = array( 'http://tile.openstreetmap.org/', 'https://t
 $wgNoFollowDomainExceptions = array( 'www.openstreetmap.org', 'josm.openstreetmap.de', 'taginfo.openstreetmap.org', 'blog.openstreetmap.org', 'wiki.osmfoundation.org' );
 
 # FIXME - move to specific
-$wgForceUIMsgAsContentMsg = array( 'mainpage-url', 'portal-url', 'mapfeatures-url', 'helppage' );
+# defines which links of the sidebar are translatable 
+$wgForceUIMsgAsContentMsg = array( 'mainpage-url', 'mapfeatures-url', 'contributors-url', 'helppage', 'blogs-url', 'shop-url', 'sitesupport-url' );
 
 # FIXME - move to specific
 $wgAllowUserJs = TRUE;
index d5485a6204bb46b713cced32ad4b66c18486ad3d..3182f8d587840c42391fec91afebe1f2d14cada9 100644 (file)
 
   DocumentRoot <%= @directory %>
 
-  php_admin_value open_basedir <%= @directory %>/:/usr/share/php/:/dev/null:/tmp/
-  #php_admin_value disable_functions "exec,shell_exec,system,passthru,popen,proc_open"
-  php_value memory_limit 500M
-  php_value max_execution_time 240
-  php_value upload_max_filesize 70M
-  php_value post_max_size 100M
+  ProxyTimeout 300
 
   RewriteCond %{SERVER_NAME} !=<%= @name %>
   RewriteRule ^/(.*)$ https://<%= @name %>/$1 [R=permanent]
   <Directory <%= @directory %>>
     Options -Indexes
     Require all granted
+
+    <FilesMatch ".+\.ph(ar|p|tml)$">
+      SetHandler "proxy:unix:/run/php/<%= @name %>.sock|fcgi://127.0.0.1"
+    </FilesMatch>
   </Directory>
 
   <Directory <%= @directory %>/w/images/>
-    # No php execution in the upload area
-    php_admin_flag engine off
     Options -ExecCGI -Includes -Indexes
     AllowOverride None
     AddType text/plain .html .htm .shtml
 <% if @private_site -%>
     Require all denied
 <% end -%>
+    <FilesMatch ".+\.ph(ar|p|tml)$">
+      SetHandler None
+    </FilesMatch>
   </Directory>
 
   <Directory <%= @directory %>/w/images/thumb/>
     Options -ExecCGI -Includes -Indexes
     AllowOverride None
     AddType text/plain .html .htm .shtml
-    php_admin_flag engine off
+    <FilesMatch ".+\.ph(ar|p|tml)$">
+      SetHandler None
+    </FilesMatch>
   </Directory>
 
   <Directory <%= @directory %>/dump/>
index ff28a185cc184d9e1c76037976b36759ffdbe391..cb4eb9ab981eea9beec4c8a9df968aaa56dd4f17 100755 (executable)
@@ -7,10 +7,9 @@ mkdir $T/wiki-<%= @name %>-$D
 echo '[mysqldump]' > $T/mysqldump.opts
 echo 'user=<%= @database_params[:username] %>' >> $T/mysqldump.opts
 echo 'password=<%= @database_params[:password] %>' >> $T/mysqldump.opts
-mysqldump --defaults-file=$T/mysqldump.opts --opt --skip-lock-tables --single-transaction "<%= @database_params[:name] %>" | lz4 -9 > $T/wiki-<%= @name %>-$D/wiki.sql.lz4
+mysqldump --defaults-file=$T/mysqldump.opts --opt --skip-lock-tables --single-transaction --no-tablespaces "<%= @database_params[:name] %>" | lz4 -9 > $T/wiki-<%= @name %>-$D/wiki.sql.lz4
 ln -s <%= @directory %>  $T/wiki-<%= @name %>-$D/www
-export GZIP="--rsyncable -9" #make backup rsyncable
-nice tar --create --gzip --dereference --directory=$T --warning=no-file-changed --exclude=wiki-<%= @name %>-$D/www/w/images/thumb --exclude=wiki-<%= @name %>-$D/www/w/.git --exclude=wiki-<%= @name %>-$D/www/w/extensions/*/.git --file=$T/$B wiki-<%= @name %>-$D
+nice tar --create --dereference --directory=$T --warning=no-file-changed --exclude=wiki-<%= @name %>-$D/www/w/images/thumb --exclude=wiki-<%= @name %>-$D/www/w/.git --exclude=wiki-<%= @name %>-$D/www/w/extensions/*/.git wiki-<%= @name %>-$D | nice gzip --rsyncable -9 > $T/$B
 nice rsync --preallocate --fuzzy $T/$B backup::backup
 
 rm -rf $T
diff --git a/cookbooks/mediawiki/templates/default/mediawiki.cron.erb b/cookbooks/mediawiki/templates/default/mediawiki.cron.erb
deleted file mode 100644 (file)
index a6d996b..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# Generate sitemap.xml daily
-30 0 * * * <%= @user %> /usr/bin/nice /usr/bin/php -d memory_limit=1024M -d error_reporting=22517 <%= @directory %>/w/maintenance/generateSitemap.php --server="https://<%= @name %>" --urlpath="https://<%= @name %>/" --fspath="<%= @directory %>" --quiet --skip-redirects
-# Run mediawiki jobs
-*/3 * * * * <%= @user %> /usr/bin/nice /usr/bin/php -d memory_limit=1024M -d error_reporting=22517 <%= @directory %>/w/maintenance/runJobs.php --server="https://<%= @name %>" --maxtime=160 --memory-limit=1024M --procs=8 --quiet
-# Run mediawiki email jobs
-* * * * * <%= @user %> /usr/bin/nice /usr/bin/php -d memory_limit=1024M -d error_reporting=22517 <%= @directory %>/w/maintenance/runJobs.php --server="https://<%= @name %>" --maxtime=30 --type=enotifNotify --memory-limit=1024M --procs=4 --quiet
-# Run mediawiki refresh links table weekly
-5 0 * * 0 <%= @user %> /usr/bin/nice /usr/bin/php -d memory_limit=1024M -d error_reporting=22517 <%= @directory %>/w/maintenance/refreshLinks.php --server="https://<%= @name %>" --memory-limit=1024M --quiet
-
-# Clean up imagemagic garbage
-10 2 * * * <%= @user %> /usr/bin/find /tmp/ -maxdepth 1 -type f -user www-data -mmin +90 -name 'gs_*' -delete
-20 2 * * * <%= @user %> /usr/bin/find /tmp/ -maxdepth 1 -type f -user www-data -mmin +90 -name 'magick-*' -delete
index 4c9216ac0d9b9cd7a7510734671593ea841f09e6..09f5814b872dab175343bc68045a39a22de4ba3b 100644 (file)
@@ -8,3 +8,8 @@ $wgGroupPermissions['*']['abusefilter-log'] = true;
 $wgGroupPermissions['sysop']['abusefilter-private'] = true;
 $wgGroupPermissions['sysop']['abusefilter-modify-restricted'] = true;
 $wgGroupPermissions['sysop']['abusefilter-revert'] = true;
+
+# Tune AbuseFilter limits
+# https://github.com/openstreetmap/operations/issues/353
+$wgAbuseFilterEmergencyDisableThreshold['default'] = 0.30; # 30%
+$wgAbuseFilterEmergencyDisableCount['default'] = 25;
index 7f69d41bb2fb93d41d6dec92cefee8c29b7a7f14..44485f2c3b067670c65ab6d8341c35a0374907eb 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 # DO NOT EDIT - This file is being maintained by Chef
-require_once($IP .'/extensions/CirrusSearch/CirrusSearch.php');
+wfLoadExtension( 'CirrusSearch' );
 $wgDisableSearchUpdate = false;
 $wgSearchType = 'CirrusSearch';
 
diff --git a/cookbooks/mediawiki/templates/default/mw-ext-SlippyMap.inc.php.erb b/cookbooks/mediawiki/templates/default/mw-ext-SlippyMap.inc.php.erb
deleted file mode 100644 (file)
index 00aee9c..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php
-# DO NOT EDIT - This file is being maintained by Chef
-require_once($IP .'/extensions/SlippyMap/SlippyMap.php');
index e9dd85c82b2dfdfaa69b2076403fe2782a54109e..f07fa1cdce47f4fc73bb7af4e6e3b95ddd825b9d 100644 (file)
@@ -6,3 +6,5 @@ description       "Installs and configures memcached"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "munin"
+depends           "prometheus"
index 8c1b427b18806f2b37551cb4e2bc97733785cead..56916ec9ea253723cb35a633908ba249367ee42f 100644 (file)
@@ -17,6 +17,9 @@
 # limitations under the License.
 #
 
+include_recipe "munin"
+include_recipe "prometheus"
+
 package "memcached"
 
 service "memcached" do
@@ -28,7 +31,7 @@ template "/etc/memcached.conf" do
   source "memcached.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[memcached]"
 end
 
@@ -41,3 +44,8 @@ end
     target "memcached_multi_"
   end
 end
+
+prometheus_exporter "memcached" do
+  port 9150
+  options "--memcached.address=#{node[:memcached][:ip_address]}:#{node[:memcached][:tcp_port]} --memcached.pid-file=/run/memcached/memcached.pid"
+end
index 93ff610840faa678c8b75059b9124692c5425ffd..7b60de4667797752c78b49de7aa3f1c2013655ae 100644 (file)
@@ -6,6 +6,9 @@
 # Run as user memcache
 -u memcache
 
+# Use a pidfile
+-P /run/memcached/memcached.pid
+
 # Log memcached's output to /var/log/memcached
 logfile /var/log/memcached.log
 
index ea95ed137d4f5133684613538ea13e3d7fcae0a5..4eae910dd7d8cbada42558b36fdc4adcdbe21004 100755 (executable)
@@ -12,9 +12,9 @@ def uris_from_status(server)
   rows = (tables[1] / "tr")[1..-1]
   data = rows.collect { |r| (r / "td").collect(&:inner_html) }
   # filter where the PID is numeric, status is 'W' and host matches the server
-  matching_data = data.select { |r| r[1].to_i.positive? && r[3].match(/W/) && r[11].match(server) }
+  matching_data = data.select { |r| r[1].to_i.positive? && r[3].match(/W/) && r[12].match(server) }
   # return only the URI part
-  matching_data.collect { |r| r[12] }
+  matching_data.collect { |r| r[13] }
 end
 
 CALL_TYPES = {
index f575dad1c6df39a3b0e36df4ebe4e35822b6a3c7..3d511ec8cb5bc0582f54281c6cb5c9a5859b6567 100755 (executable)
@@ -12,9 +12,9 @@ def uri_and_times_from_status(server)
   rows = (tables[1] / "tr")[1..-1]
   data = rows.collect { |r| (r / "td").collect(&:inner_html) }
   # filter where the PID is numeric, status is 'W' and host matches the server
-  matching_data = data.select { |r| r[1].to_i.positive? && r[3].match(/W/) && r[11].match(server) }
+  matching_data = data.select { |r| r[1].to_i.positive? && r[3].match(/W/) && r[12].match(server) }
   # return URI and number of seconds processing for each request
-  matching_data.collect { |r| [r[12], r[5].to_i] }
+  matching_data.collect { |r| [r[13], r[5].to_i] }
 end
 
 CALL_TYPES = {
index cf2b767ab438e3df8b5ad4a44759c1373fe1e60b..aad5d40d8dd1b3e95dd0d85bcb92ba37efb28bcb 100644 (file)
@@ -44,288 +44,7 @@ template "/etc/munin/munin-node.conf" do
   source "munin-node.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   variables :servers => servers
   notifies :restart, "service[munin-node]"
 end
-
-remote_directory "/usr/local/share/munin/plugins" do
-  source "plugins"
-  owner "root"
-  group "root"
-  mode 0o755
-  files_owner "root"
-  files_group "root"
-  files_mode 0o755
-  purge true
-end
-
-remote_directory "/etc/munin/plugin-conf.d" do
-  source "plugin-conf.d"
-  owner "root"
-  group "munin"
-  mode 0o750
-  files_owner "root"
-  files_group "root"
-  files_mode 0o644
-  purge false
-  notifies :restart, "service[munin-node]"
-end
-
-if Dir.glob("/proc/acpi/thermal_zone/*/temperature").empty?
-  munin_plugin "acpi" do
-    action :delete
-  end
-else
-  munin_plugin "acpi"
-end
-
-# apcpdu_
-munin_plugin "cpu"
-
-if File.exist?("/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state")
-  munin_plugin "cpuspeed"
-else
-  munin_plugin "cpuspeed" do
-    action :delete
-  end
-end
-
-munin_plugin_conf "df" do
-  template "df.erb"
-end
-
-munin_plugin "df"
-munin_plugin "df_inode"
-
-munin_plugin_conf "diskstats" do
-  template "diskstats.erb"
-end
-
-munin_plugin "diskstats"
-munin_plugin "entropy"
-munin_plugin "forks"
-
-if node[:kernel][:modules].include?("nf_conntrack")
-  package "conntrack"
-
-  munin_plugin "fw_conntrack"
-  munin_plugin "fw_forwarded_local"
-else
-  munin_plugin "fw_conntrack" do
-    action :delete
-  end
-
-  munin_plugin "fw_forwarded_local" do
-    action :delete
-  end
-end
-
-if File.read("/proc/sys/net/ipv4/ip_forward").chomp == "1"
-  munin_plugin "fw_packets"
-else
-  munin_plugin "fw_packets" do
-    action :delete
-  end
-end
-
-if File.exist?("/sbin/hpasmcli")
-  munin_plugin "hpasmcli2_temp" do
-    target "hpasmcli2_"
-  end
-
-  munin_plugin "hpasmcli2_fans" do
-    target "hpasmcli2_"
-  end
-else
-  munin_plugin "hpasmcli2_temp" do
-    action :delete
-  end
-
-  munin_plugin "hpasmcli2_fans" do
-    action :delete
-  end
-end
-
-munin_plugin "hpasmcli_temp" do
-  action :delete
-end
-
-munin_plugin "hpasmcli_fans" do
-  action :delete
-end
-
-munin_plugin "http_loadtime" do
-  action :delete
-end
-
-node[:network][:interfaces].each do |ifname, ifattr|
-  if ifattr[:flags]&.include?("UP") && !ifattr[:flags].include?("LOOPBACK")
-    if node[:hardware] &&
-       node[:hardware][:network] &&
-       node[:hardware][:network][ifname][:device] =~ /^virtio/
-      munin_plugin_conf "if_#{ifname}" do
-        template "if.erb"
-        variables :ifname => ifname
-      end
-    else
-      munin_plugin_conf "if_#{ifname}" do
-        action :delete
-      end
-    end
-
-    munin_plugin "if_err_#{ifname}" do
-      target "if_err_"
-    end
-
-    munin_plugin "if_#{ifname}" do
-      target "if_"
-    end
-  else
-    munin_plugin "if_err_#{ifname}" do
-      action :delete
-    end
-
-    munin_plugin "if_#{ifname}" do
-      action :delete
-    end
-  end
-end
-
-munin_plugin "interrupts"
-munin_plugin "iostat"
-munin_plugin "iostat_ios"
-
-if Dir.glob("/dev/ipmi*").empty?
-  munin_plugin_conf "ipmi" do
-    action :delete
-  end
-
-  munin_plugin "ipmi_fans" do
-    action :delete
-  end
-
-  munin_plugin "ipmi_temp" do
-    action :delete
-  end
-
-  munin_plugin "ipmi_power" do
-    action :delete
-  end
-else
-  munin_plugin_conf "ipmi" do
-    template "ipmi.erb"
-  end
-
-  munin_plugin "ipmi_fans" do
-    target "ipmi_"
-  end
-
-  munin_plugin "ipmi_temp" do
-    target "ipmi_"
-  end
-
-  munin_plugin "ipmi_power" do
-    target "ipmi_"
-  end
-end
-
-munin_plugin "irqstats"
-munin_plugin "load"
-munin_plugin "memory"
-munin_plugin "netstat"
-
-if node[:kernel][:modules].include?("nfsv3")
-  munin_plugin "nfs_client"
-else
-  munin_plugin "nfs_client" do
-    action :delete
-  end
-end
-
-if node[:kernel][:modules].include?("nfsv4")
-  munin_plugin "nfs4_client"
-else
-  munin_plugin "nfs4_client" do
-    action :delete
-  end
-end
-
-if node[:kernel][:modules].include?("nfsd")
-  munin_plugin "nfsd"
-  munin_plugin "nfsd4"
-else
-  munin_plugin "nfsd" do
-    action :delete
-  end
-
-  munin_plugin "nfsd4" do
-    action :delete
-  end
-end
-
-munin_plugin "open_files"
-munin_plugin "open_inodes"
-
-munin_plugin "postfix_mailqueue" do
-  action :delete
-end
-
-munin_plugin "postfix_mailvolume" do
-  action :delete
-end
-
-munin_plugin "processes"
-munin_plugin "proc_pri"
-
-sensors_fan = false
-sensors_temp = false
-sensors_volt = false
-
-Dir.glob("/sys/class/hwmon/hwmon*").each do |hwmon|
-  hwmon = "#{hwmon}/device" unless File.exist?("#{hwmon}/name")
-
-  sensors_fan = true unless Dir.glob("#{hwmon}/fan*_input").empty?
-  sensors_temp = true unless Dir.glob("#{hwmon}/temp*_input").empty?
-  sensors_volt = true unless Dir.glob("#{hwmon}/in*_input").empty?
-end
-
-package "lm-sensors" if sensors_fan || sensors_temp || sensors_volt
-
-if sensors_fan
-  munin_plugin "sensors_fan" do
-    target "sensors_"
-  end
-else
-  munin_plugin "sensors_fan" do
-    action :delete
-  end
-end
-
-if sensors_temp
-  munin_plugin "sensors_temp" do
-    target "sensors_"
-  end
-else
-  munin_plugin "sensors_temp" do
-    action :delete
-  end
-end
-
-if sensors_volt
-  munin_plugin "sensors_volt" do
-    target "sensors_"
-    conf "sensors_volt.erb"
-  end
-else
-  munin_plugin "sensors_volt" do
-    action :delete
-  end
-end
-
-munin_plugin "swap"
-munin_plugin "tcp"
-munin_plugin "threads"
-munin_plugin "uptime"
-munin_plugin "users"
-munin_plugin "vmstat"
diff --git a/cookbooks/munin/recipes/plugins.rb b/cookbooks/munin/recipes/plugins.rb
new file mode 100644 (file)
index 0000000..7b8eb1a
--- /dev/null
@@ -0,0 +1,301 @@
+#
+# Cookbook:: munin
+# Recipe:: default
+#
+# Copyright:: 2010, OpenStreetMap Foundation
+#
+# 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
+#
+#     https://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.
+#
+
+include_recipe "munin"
+
+remote_directory "/usr/local/share/munin/plugins" do
+  source "plugins"
+  owner "root"
+  group "root"
+  mode "755"
+  files_owner "root"
+  files_group "root"
+  files_mode "755"
+  purge true
+end
+
+remote_directory "/etc/munin/plugin-conf.d" do
+  source "plugin-conf.d"
+  owner "root"
+  group "munin"
+  mode "750"
+  files_owner "root"
+  files_group "root"
+  files_mode "644"
+  purge false
+  notifies :restart, "service[munin-node]"
+end
+
+if Dir.glob("/proc/acpi/thermal_zone/*/temperature").empty?
+  munin_plugin "acpi" do
+    action :delete
+  end
+else
+  munin_plugin "acpi"
+end
+
+# apcpdu_
+munin_plugin "cpu"
+
+if File.exist?("/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state")
+  munin_plugin "cpuspeed"
+else
+  munin_plugin "cpuspeed" do
+    action :delete
+  end
+end
+
+munin_plugin_conf "df" do
+  template "df.erb"
+end
+
+munin_plugin "df"
+munin_plugin "df_inode"
+
+munin_plugin_conf "diskstats" do
+  template "diskstats.erb"
+end
+
+munin_plugin "diskstats"
+munin_plugin "entropy"
+munin_plugin "forks"
+
+if node[:kernel][:modules].include?("nf_conntrack")
+  package "conntrack"
+
+  munin_plugin "fw_conntrack"
+  munin_plugin "fw_forwarded_local"
+else
+  munin_plugin "fw_conntrack" do
+    action :delete
+  end
+
+  munin_plugin "fw_forwarded_local" do
+    action :delete
+  end
+end
+
+if File.read("/proc/sys/net/ipv4/ip_forward").chomp == "1"
+  munin_plugin "fw_packets"
+else
+  munin_plugin "fw_packets" do
+    action :delete
+  end
+end
+
+if File.exist?("/sbin/hpasmcli")
+  munin_plugin "hpasmcli2_temp" do
+    target "hpasmcli2_"
+  end
+
+  munin_plugin "hpasmcli2_fans" do
+    target "hpasmcli2_"
+  end
+else
+  munin_plugin "hpasmcli2_temp" do
+    action :delete
+  end
+
+  munin_plugin "hpasmcli2_fans" do
+    action :delete
+  end
+end
+
+munin_plugin "hpasmcli_temp" do
+  action :delete
+end
+
+munin_plugin "hpasmcli_fans" do
+  action :delete
+end
+
+munin_plugin "http_loadtime" do
+  action :delete
+end
+
+node[:network][:interfaces].each do |ifname, ifattr|
+  if ifattr[:flags]&.include?("UP") && !ifattr[:flags].include?("LOOPBACK")
+    if node[:hardware] &&
+       node[:hardware][:network] &&
+       node[:hardware][:network][ifname][:device] =~ /^virtio/
+      munin_plugin_conf "if_#{ifname}" do
+        template "if.erb"
+        variables :ifname => ifname
+      end
+    else
+      munin_plugin_conf "if_#{ifname}" do
+        action :delete
+      end
+    end
+
+    munin_plugin "if_err_#{ifname}" do
+      target "if_err_"
+    end
+
+    munin_plugin "if_#{ifname}" do
+      target "if_"
+    end
+  else
+    munin_plugin "if_err_#{ifname}" do
+      action :delete
+    end
+
+    munin_plugin "if_#{ifname}" do
+      action :delete
+    end
+  end
+end
+
+munin_plugin "interrupts"
+munin_plugin "iostat"
+munin_plugin "iostat_ios"
+
+if Dir.glob("/dev/ipmi*").empty?
+  munin_plugin_conf "ipmi" do
+    action :delete
+  end
+
+  munin_plugin "ipmi_fans" do
+    action :delete
+  end
+
+  munin_plugin "ipmi_temp" do
+    action :delete
+  end
+
+  munin_plugin "ipmi_power" do
+    action :delete
+  end
+else
+  munin_plugin_conf "ipmi" do
+    template "ipmi.erb"
+  end
+
+  munin_plugin "ipmi_fans" do
+    target "ipmi_"
+  end
+
+  munin_plugin "ipmi_temp" do
+    target "ipmi_"
+  end
+
+  munin_plugin "ipmi_power" do
+    target "ipmi_"
+  end
+end
+
+munin_plugin "irqstats"
+munin_plugin "load"
+munin_plugin "memory"
+munin_plugin "netstat"
+
+if node[:kernel][:modules].include?("nfsv3")
+  munin_plugin "nfs_client"
+else
+  munin_plugin "nfs_client" do
+    action :delete
+  end
+end
+
+if node[:kernel][:modules].include?("nfsv4")
+  munin_plugin "nfs4_client"
+else
+  munin_plugin "nfs4_client" do
+    action :delete
+  end
+end
+
+if node[:kernel][:modules].include?("nfsd")
+  munin_plugin "nfsd"
+  munin_plugin "nfsd4"
+else
+  munin_plugin "nfsd" do
+    action :delete
+  end
+
+  munin_plugin "nfsd4" do
+    action :delete
+  end
+end
+
+munin_plugin "open_files"
+munin_plugin "open_inodes"
+
+munin_plugin "postfix_mailqueue" do
+  action :delete
+end
+
+munin_plugin "postfix_mailvolume" do
+  action :delete
+end
+
+munin_plugin "processes"
+munin_plugin "proc_pri"
+
+sensors_fan = false
+sensors_temp = false
+sensors_volt = false
+
+Dir.glob("/sys/class/hwmon/hwmon*").each do |hwmon|
+  hwmon = "#{hwmon}/device" unless File.exist?("#{hwmon}/name")
+
+  sensors_fan = true unless Dir.glob("#{hwmon}/fan*_input").empty?
+  sensors_temp = true unless Dir.glob("#{hwmon}/temp*_input").empty?
+  sensors_volt = true unless Dir.glob("#{hwmon}/in*_input").empty?
+end
+
+package "lm-sensors" if sensors_fan || sensors_temp || sensors_volt
+
+if sensors_fan
+  munin_plugin "sensors_fan" do
+    target "sensors_"
+  end
+else
+  munin_plugin "sensors_fan" do
+    action :delete
+  end
+end
+
+if sensors_temp
+  munin_plugin "sensors_temp" do
+    target "sensors_"
+  end
+else
+  munin_plugin "sensors_temp" do
+    action :delete
+  end
+end
+
+if sensors_volt
+  munin_plugin "sensors_volt" do
+    target "sensors_"
+    conf "sensors_volt.erb"
+  end
+else
+  munin_plugin "sensors_volt" do
+    action :delete
+  end
+end
+
+munin_plugin "swap"
+munin_plugin "tcp"
+munin_plugin "threads"
+munin_plugin "uptime"
+munin_plugin "users"
+munin_plugin "vmstat"
index f9fe98def6e1acd18c7cb0054c1c540c37c25e40..b3f64c4589950210c1328bd9a0e0fc04df6a8d5f 100644 (file)
@@ -27,13 +27,13 @@ template "/etc/default/rrdcached" do
   source "rrdcached.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 directory "/var/lib/munin/rrdcached" do
   owner "munin"
   group "munin"
-  mode 0o755
+  mode "755"
 end
 
 service "rrdcached" do
@@ -46,8 +46,9 @@ munin_plugin "rrdcached"
 expiry_time = 14 * 86400
 
 clients = search(:node, "recipes:munin\\:\\:default").sort_by(&:name)
-frontends = search(:node, "recipes:web\\:\\:frontend").reject { |n| Time.now - Time.at(n[:ohai_time]) > expiry_time }.map(&:name).sort
-backends = search(:node, "recipes:web\\:\\:backend").reject { |n| Time.now - Time.at(n[:ohai_time]) > expiry_time }.map(&:name).sort
+frontends = search(:node, "recipes:web\\:\\:frontend").reject { |n| Time.now - Time.at(n[:ohai_time]) > expiry_time }.sort_by(&:name).map do |n|
+  { :name => n.name.split(".").first, :interface => n.interfaces(:role => :external).first[:interface].tr(".", "_") }
+end
 tilecaches = search(:node, "roles:tilecache").reject { |n| Time.now - Time.at(n[:ohai_time]) > expiry_time }.sort_by(&:name).map do |n|
   { :name => n.name.split(".").first, :interface => n.interfaces(:role => :external).first[:interface].tr(".", "_") }
 end
@@ -62,11 +63,10 @@ template "/etc/munin/munin.conf" do
   source "munin.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   variables :expiry_time => expiry_time, :clients => clients,
-            :frontends => frontends, :backends => backends,
-            :tilecaches => tilecaches, :renderers => renderers,
-            :geocoders => geocoders
+            :frontends => frontends, :geocoders => geocoders,
+            :tilecaches => tilecaches, :renderers => renderers
 end
 
 apache_module "fcgid"
@@ -77,17 +77,17 @@ remote_directory "/srv/munin.openstreetmap.org" do
   source "www"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   files_owner "root"
   files_group "root"
-  files_mode 0o644
+  files_mode "644"
 end
 
 # directory to put dumped files in
 directory "/srv/munin.openstreetmap.org/dumps" do
   owner "www-data"
   group "www-data"
-  mode 0o755
+  mode "755"
 end
 
 ssl_certificate "munin.openstreetmap.org" do
@@ -103,7 +103,7 @@ template "/etc/cron.daily/munin-backup" do
   source "backup.cron.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 munin_plugin "munin_stats"
index dede3cb534360b59b55b0650179ed77a1b0f8e36..bc58bf9751df3cd0b2ce6a07386883f5a54a1e73 100644 (file)
@@ -19,7 +19,7 @@
 
 default_action :create
 
-property :plugin, :kind_of => String, :name_attribute => true
+property :plugin, :kind_of => String, :name_property => true
 property :target, :kind_of => String
 property :conf, :kind_of => String
 property :conf_cookbook, :kind_of => String
@@ -81,5 +81,5 @@ action_class do
 end
 
 def after_created
-  notifies :restart, "service[munin-node]" if restart_munin && node[:recipes].include?("munin")
+  notifies :restart, "service[munin-node]" if restart_munin
 end
index 1355052d7b13162f42dea0079d1195b3bb373ccb..6105f0d2b94b4e7bc6f11f1724148b6e177cd5c8 100644 (file)
@@ -19,9 +19,9 @@
 
 default_action :create
 
-property :plugin_conf, :kind_of => String, :name_attribute => true
+property :plugin_conf, :kind_of => String, :name_property => true
 property :cookbook, :kind_of => [String, nil]
-property :template, :kind_of => String, :required => true
+property :template, :kind_of => String, :required => [:create]
 property :variables, :kind_of => Hash, :default => {}
 property :restart_munin, :kind_of => [TrueClass, FalseClass], :default => true
 
@@ -31,7 +31,7 @@ action :create do
     source new_resource.template
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables new_resource.variables.merge(:name => new_resource.plugin_conf)
   end
 end
index 77a215704ca22b3a590bec549d322a907ec9d09e..ed922b34acc39ad0cc74f23565ceb3e37be778f1 100644 (file)
@@ -1,59 +1,59 @@
 # DO NOT EDIT - This file is being maintained by Chef
 
 <VirtualHost *:443>
-       ServerName munin.openstreetmap.org
-       ServerAlias munin.osm.org
-       ServerAdmin webmaster@openstreetmap.org
+  ServerName munin.openstreetmap.org
+  ServerAlias munin.osm.org
+  ServerAdmin webmaster@openstreetmap.org
 
-       CustomLog /var/log/apache2/munin.openstreetmap.org-access.log combined
-       ErrorLog /var/log/apache2/munin.openstreetmap.org-error.log
+  CustomLog /var/log/apache2/munin.openstreetmap.org-access.log combined
+  ErrorLog /var/log/apache2/munin.openstreetmap.org-error.log
 
-       SSLEngine on
-       SSLCertificateFile /etc/ssl/certs/munin.openstreetmap.org.pem
-       SSLCertificateKeyFile /etc/ssl/private/munin.openstreetmap.org.key
+  SSLEngine on
+  SSLCertificateFile /etc/ssl/certs/munin.openstreetmap.org.pem
+  SSLCertificateKeyFile /etc/ssl/private/munin.openstreetmap.org.key
 
-        SetEnv RRDCACHED_ADDRESS /var/run/rrdcached.sock
+  SetEnv RRDCACHED_ADDRESS /var/run/rrdcached.sock
 
-       DocumentRoot /srv/munin.openstreetmap.org
-       Alias /static/favicon.ico /srv/munin.openstreetmap.org/favicon.ico
-       Alias /static/ /etc/munin/static/
-       ScriptAlias /munin-cgi/ /usr/lib/munin/cgi/
+  DocumentRoot /srv/munin.openstreetmap.org
+  Alias /static/favicon.ico /srv/munin.openstreetmap.org/favicon.ico
+  Alias /static/ /etc/munin/static/
+  ScriptAlias /munin-cgi/ /usr/lib/munin/cgi/
 
-       # Remove Proxy request header to mitigate https://httpoxy.org/
-       RequestHeader unset Proxy early
+  # Remove Proxy request header to mitigate https://httpoxy.org/
+  RequestHeader unset Proxy early
 
-       RewriteEngine on
-       RewriteCond %{REQUEST_URI} !^/static/
-       RewriteCond %{REQUEST_URI} !^/dumps/
-       RewriteRule ^(/.*\.html)?$ /munin-cgi/munin-cgi-html/$1 [PT]
+  RewriteEngine on
+  RewriteCond %{REQUEST_URI} !^/static/
+  RewriteCond %{REQUEST_URI} !^/dumps/
+  RewriteRule ^(/.*\.html)?$ /munin-cgi/munin-cgi-html/$1 [PT]
 </VirtualHost>
 
 <VirtualHost *:80>
-       ServerName munin.openstreetmap.org
-       ServerAlias munin.osm.org
-       ServerAdmin webmaster@openstreetmap.org
+  ServerName munin.openstreetmap.org
+  ServerAlias munin.osm.org
+  ServerAdmin webmaster@openstreetmap.org
 
-       CustomLog /var/log/apache2/munin.openstreetmap.org-access.log combined
-       ErrorLog /var/log/apache2/munin.openstreetmap.org-error.log
+  CustomLog /var/log/apache2/munin.openstreetmap.org-access.log combined
+  ErrorLog /var/log/apache2/munin.openstreetmap.org-error.log
 
-       RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
-       RedirectPermanent / https://munin.openstreetmap.org/
+  RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
+  RedirectPermanent / https://munin.openstreetmap.org/
 </VirtualHost>
 
 <Directory /srv/munin.openstreetmap.org>
-       Require all granted
+  Require all granted
 </Directory>
 
 <Directory /srv/munin.openstreetmap.org/dumps>
-       Options +Indexes
+  Options +Indexes
 </Directory>
 
 <Directory /etc/munin/static>
-       Require all granted
+  Require all granted
 </Directory>
 
 <Directory /usr/lib/munin/cgi>
-       Options +ExecCGI
-       SetHandler fcgid-script
-       Require all granted
+  Options +ExecCGI
+  SetHandler fcgid-script
+  Require all granted
 </Directory>
index 6b846057769f8d03d443bfeba94a516a817d341b..13d4228cecb3bab14b035acffbaf2880f16ec853 100644 (file)
@@ -10,10 +10,9 @@ mkdir $T/munin-$D
 ln -s /var/lib/munin/openstreetmap $T/munin-$D
 ln -s /var/lib/munin/*.storable $T/munin-$D
 
-export GZIP="--rsyncable -9"
 export RSYNC_RSH="ssh -ax"
 
-nice tar --create --gzip --dereference --directory=$T --file=$T/$B munin-$D
+nice tar --create --dereference --directory=$T --warning=no-file-removed munin-$D | nice gzip --rsyncable -9 > $T/$B
 nice rsync --preallocate --fuzzy $T/$B backup::backup
 
 rm -rf $T
index 8c88fd612560beb70ebf675fb11d009136bca39d..4f3580b563ba9e7a1eec94e333c6d8fdf43f39fb 100644 (file)
@@ -35,9 +35,6 @@ allow ^127\.0\.0\.1$
 <% server.interfaces do |interface| -%>
 allow ^<%= Regexp.quote(interface[:address]) %>$
 <% end -%>
-<% if server[:openvpn] -%>
-allow ^<%= Regexp.quote(server[:openvpn][:address]) %>$
-<% end -%>
 <% end -%>
 <% node[:munin][:allow].each do |address| -%>
 allow ^<%= Regexp.quote(address) %>$
index add1593d8ceb61ca170ff1dfa35db324bed2dc81..3aa31b432d91773c7b002caf6fa5aae6738353fd 100644 (file)
@@ -148,7 +148,7 @@ unknown_limit 144
     apcpdu_humidity.humidity.label Humidity
     apcpdu_humidity.humidity.draw LINE2
     apcpdu_humidity.humidity.min 0
-<% unless @frontends.empty? && @backends.empty? -%>
+<% unless @frontends.empty? -%>
 
 # Configure compound graphs for www.openstreetmap.org
 [www.openstreetmap.org]
@@ -157,201 +157,205 @@ unknown_limit 144
     apache_accesses.graph_vlabel accesses / ${graph_period}
     apache_accesses.graph_category apache
     apache_accesses.graph_args --lower-limit 0
-    apache_accesses.accesses80.sum <%= Chef::Munin.expand "%%:apache_accesses.accesses80", @frontends %>
+    apache_accesses.accesses80.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:apache_accesses.accesses80", @frontends %>
     apache_accesses.accesses80.label port 80
     apache_accesses.accesses80.min 0
     apache_volume.graph_title Apache volume
     apache_volume.graph_vlabel bytes per ${graph_period}
     apache_volume.graph_category apache
     apache_volume.graph_args --lower-limit 0
-    apache_volume.volume80.sum <%= Chef::Munin.expand "%%:apache_volume.volume80", @frontends %>
+    apache_volume.volume80.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:apache_volume.volume80", @frontends %>
     apache_volume.volume80.label port 80
     apache_volume.volume80.min 0
-    if_eth0.graph_title eth0 traffic
-    if_eth0.graph_vlabel bits in (-) / out (+) per ${graph_period}
-    if_eth0.graph_category network
-    if_eth0.graph_order down up
-    if_eth0.down.sum <%= Chef::Munin.expand "%%:if_eth0.down", @frontends %>
-    if_eth0.down.label received
-    if_eth0.down.cdef down,8,*
-    if_eth0.up.sum <%= Chef::Munin.expand "%%:if_eth0.up", @frontends %>
-    if_eth0.up.label sent
-    if_eth0.up.cdef up,8,*
-    if_eth1.graph_title eth1 traffic
-    if_eth1.graph_vlabel bits in (-) / out (+) per ${graph_period}
-    if_eth1.graph_category network
-    if_eth1.graph_order down up
-    if_eth1.down.sum <%= Chef::Munin.expand "%%:if_eth1.down", @frontends %>
-    if_eth1.down.label received
-    if_eth1.down.cdef down,8,*
-    if_eth1.up.sum <%= Chef::Munin.expand "%%:if_eth1.up", @frontends %>
-    if_eth1.up.label sent
-    if_eth1.up.cdef up,8,*
+    network_in.graph_title Inbound network traffic
+    network_in.graph_vlabel bits in per ${graph_period}
+    network_in.graph_category network
+    network_in.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:if_%%interface%%.down", @frontends %>
+    network_in.graph_total total
+    network_in.graph_args --lower-limit 0
+<% @frontends.each do |fe| -%>
+    network_in.<%= fe[:name].tr("-", "_") %>.label <%= fe[:name] %>
+    network_in.<%= fe[:name].tr("-", "_") %>.cdef <%= fe[:name].tr("-", "_") %>,8,*
+    network_in.<%= fe[:name].tr("-", "_") %>.draw AREASTACK
+    network_in.<%= fe[:name].tr("-", "_") %>.min 0
+<% end -%>
+    network_out.graph_title Outbound network traffic
+    network_out.graph_vlabel bits out per ${graph_period}
+    network_out.graph_category network
+    network_out.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:if_%%interface%%.up", @frontends %>
+    network_out.graph_total total
+    network_out.graph_args --lower-limit 0
+<% @frontends.each do |fe| -%>
+    network_out.<%= fe[:name].tr("-", "_") %>.label <%= fe[:name] %>
+    network_out.<%= fe[:name].tr("-", "_") %>.cdef <%= fe[:name].tr("-", "_") %>,8,*
+    network_out.<%= fe[:name].tr("-", "_") %>.draw AREASTACK
+    network_out.<%= fe[:name].tr("-", "_") %>.min 0
+<% end -%>
     api_calls_www.graph_title Active requests
     api_calls_www.graph_vlabel Number of requests
     api_calls_www.graph_category api
     api_calls_www.graph_order map upload amf history full trkpts web other
-    api_calls_www.web.sum <%= Chef::Munin.expand "%%:api_calls_%%%.web", @frontends %>
+    api_calls_www.web.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.web", @frontends %>
     api_calls_www.web.label Web site traffic
-    api_calls_www.upload.sum <%= Chef::Munin.expand "%%:api_calls_%%%.upload", @frontends %>
+    api_calls_www.upload.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.upload", @frontends %>
     api_calls_www.upload.label Changeset diff uploads
-    api_calls_www.other.sum <%= Chef::Munin.expand "%%:api_calls_%%%.other", @frontends %>
+    api_calls_www.other.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.other", @frontends %>
     api_calls_www.other.label Other API calls
-    api_calls_www.amf.sum <%= Chef::Munin.expand "%%:api_calls_%%%.amf", @frontends %>
+    api_calls_www.amf.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.amf", @frontends %>
     api_calls_www.amf.label AMF API calls
-    api_calls_www.history.sum <%= Chef::Munin.expand "%%:api_calls_%%%.history", @frontends %>
+    api_calls_www.history.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.history", @frontends %>
     api_calls_www.history.label Element history fetches
-    api_calls_www.full.sum <%= Chef::Munin.expand "%%:api_calls_%%%.full", @frontends %>
+    api_calls_www.full.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.full", @frontends %>
     api_calls_www.full.label Full element fetches
-    api_calls_www.map.sum <%= Chef::Munin.expand "%%:api_calls_%%%.map", @frontends %>
+    api_calls_www.map.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.map", @frontends %>
     api_calls_www.map.label Map API calls
-    api_calls_www.trkpts.sum <%= Chef::Munin.expand "%%:api_calls_%%%.trkpts", @frontends %>
+    api_calls_www.trkpts.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_%%%name%%%.trkpts", @frontends %>
     api_calls_www.trkpts.label GPX trackpoints calls
     api_calls_error.graph_title HTTP errors
     api_calls_error.graph_vlabel Number of errors per ${graph_period}
     api_calls_error.graph_category api
     api_calls_error.graph_order http401 http422 http500 http502 http503 http509
-    api_calls_error.http401.sum <%= Chef::Munin.expand "%%:api_calls_status.http401", @frontends %>
+    api_calls_error.http401.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_status.http401", @frontends %>
     api_calls_error.http401.label 401 Unauthorized
     api_calls_error.http401.warning :0.5
-    api_calls_error.http422.sum <%= Chef::Munin.expand "%%:api_calls_status.http422", @frontends %>
+    api_calls_error.http422.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_status.http422", @frontends %>
     api_calls_error.http422.label 422 Unprocessable Entity
     api_calls_error.http422.warning :0.5
-    api_calls_error.http500.sum <%= Chef::Munin.expand "%%:api_calls_status.http500", @frontends %>
+    api_calls_error.http500.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_status.http500", @frontends %>
     api_calls_error.http500.label 500 Internal Server Error
     api_calls_error.http500.warning :0.5
-    api_calls_error.http502.sum <%= Chef::Munin.expand "%%:api_calls_status.http502", @frontends %>
+    api_calls_error.http502.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_status.http502", @frontends %>
     api_calls_error.http502.label 502 Bad Gateway
     api_calls_error.http502.warning :0.5
-    api_calls_error.http503.sum <%= Chef::Munin.expand "%%:api_calls_status.http503", @frontends %>
+    api_calls_error.http503.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_status.http503", @frontends %>
     api_calls_error.http503.label 503 Service Unavailable
     api_calls_error.http503.warning :0.5
-    api_calls_error.http509.sum <%= Chef::Munin.expand "%%:api_calls_status.http509", @frontends %>
+    api_calls_error.http509.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_status.http509", @frontends %>
     api_calls_error.http509.label 509 Bandwidth Limit Exceeded
     api_calls_error.http509.warning :5
     api_calls_num.graph_title Requests processed
     api_calls_num.graph_vlabel Number of requests per ${graph_period}
     api_calls_num.graph_category api
     api_calls_num.graph_order map upload amf history full trkpts web other
-    api_calls_num.web.sum <%= Chef::Munin.expand "%%:api_calls_num.web", @frontends %>
+    api_calls_num.web.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.web", @frontends %>
     api_calls_num.web.label Web site traffic
-    api_calls_num.upload.sum <%= Chef::Munin.expand "%%:api_calls_num.upload", @frontends %>
+    api_calls_num.upload.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.upload", @frontends %>
     api_calls_num.upload.label Changeset diff uploads
-    api_calls_num.other.sum <%= Chef::Munin.expand "%%:api_calls_num.other", @frontends %>
+    api_calls_num.other.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.other", @frontends %>
     api_calls_num.other.label Other API calls
-    api_calls_num.amf.sum <%= Chef::Munin.expand "%%:api_calls_num.amf", @frontends %>
+    api_calls_num.amf.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.amf", @frontends %>
     api_calls_num.amf.label AMF API calls
-    api_calls_num.history.sum <%= Chef::Munin.expand "%%:api_calls_num.history", @frontends %>
+    api_calls_num.history.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.history", @frontends %>
     api_calls_num.history.label Element history fetches
-    api_calls_num.full.sum <%= Chef::Munin.expand "%%:api_calls_num.full", @frontends %>
+    api_calls_num.full.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.full", @frontends %>
     api_calls_num.full.label Full element fetches
-    api_calls_num.map.sum <%= Chef::Munin.expand "%%:api_calls_num.map", @frontends %>
+    api_calls_num.map.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.map", @frontends %>
     api_calls_num.map.label Map API calls
-    api_calls_num.trkpts.sum <%= Chef::Munin.expand "%%:api_calls_num.trkpts", @frontends %>
+    api_calls_num.trkpts.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_calls_num.trkpts", @frontends %>
     api_calls_num.trkpts.label GPX trackpoints calls
     api_waits_www.graph_title Wait times for active requests
     api_waits_www.graph_vlabel Average time of requests
     api_waits_www.graph_category api
     api_waits_www.graph_order map upload amf history full trkpts web other
-    api_waits_www.web.sum <%= Chef::Munin.expand "%%:api_waits_%%%.web", @frontends %>
+    api_waits_www.web.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.web", @frontends %>
     api_waits_www.web.label Web site traffic
     api_waits_www.web.cdef web,2,/
-    api_waits_www.upload.sum <%= Chef::Munin.expand "%%:api_waits_%%%.upload", @frontends %>
+    api_waits_www.upload.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.upload", @frontends %>
     api_waits_www.upload.label Changeset diff uploads
     api_waits_www.upload.cdef upload,2,/
-    api_waits_www.other.sum <%= Chef::Munin.expand "%%:api_waits_%%%.other", @frontends %>
+    api_waits_www.other.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.other", @frontends %>
     api_waits_www.other.label Other API calls
     api_waits_www.other.cdef other,2,/
-    api_waits_www.amf.sum <%= Chef::Munin.expand "%%:api_waits_%%%.amf", @frontends %>
+    api_waits_www.amf.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.amf", @frontends %>
     api_waits_www.amf.label AMF API calls
     api_waits_www.amf.cdef amf,2,/
-    api_waits_www.history.sum <%= Chef::Munin.expand "%%:api_waits_%%%.history", @frontends %>
+    api_waits_www.history.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.history", @frontends %>
     api_waits_www.history.label Element history fetches
     api_waits_www.history.cdef history,2,/
-    api_waits_www.full.sum <%= Chef::Munin.expand "%%:api_waits_%%%.full", @frontends %>
+    api_waits_www.full.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.full", @frontends %>
     api_waits_www.full.label Full element fetches
     api_waits_www.full.cdef full,2,/
-    api_waits_www.map.sum <%= Chef::Munin.expand "%%:api_waits_%%%.map", @frontends %>
+    api_waits_www.map.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.map", @frontends %>
     api_waits_www.map.label Map API calls
     api_waits_www.map.cdef map,2,/
-    api_waits_www.trkpts.sum <%= Chef::Munin.expand "%%:api_waits_%%%.trkpts", @frontends %>
+    api_waits_www.trkpts.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:api_waits_%%%name%%%.trkpts", @frontends %>
     api_waits_www.trkpts.label GPX trackpoints calls
     api_waits_www.trkpts.cdef trkpts,2,/
     memcached_multi_commands.graph_title Commands
     memcached_multi_commands.graph_vlabel Commands per ${graph_period}
     memcached_multi_commands.graph_category memcached
     memcached_multi_commands.graph_order cmd_get cmd_set cmd_touch get_hits get_misses delete_hits delete_misses incr_hits incr_misses decr_hits decr_misses touch_hits touch_misses
-    memcached_multi_commands.cmd_get.sum <%= Chef::Munin.expand "%%:memcached_multi_commands.cmd_get", @backends %>
+    memcached_multi_commands.cmd_get.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.cmd_get", @frontends %>
     memcached_multi_commands.cmd_get.label Gets
-    memcached_multi_commands.cmd_set.sum <%= Chef::Munin.expand "%%:memcached_multi_commands.cmd_set", @backends %>
+    memcached_multi_commands.cmd_set.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.cmd_set", @frontends %>
     memcached_multi_commands.cmd_set.label Sets
-    memcached_multi_commands.cmd_touch.sum <%= Chef::Munin.expand "%%:memcached_multi_commands.cmd_touch", @backends %>
+    memcached_multi_commands.cmd_touch.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.cmd_touch", @frontends %>
     memcached_multi_commands.cmd_touch.label Touches
-    memcached_multi_commands.get_hits.sum <%= Chef::Munin.expand "%%:memcached_multi_commands.get_hits", @backends %>
+    memcached_multi_commands.get_hits.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.get_hits", @frontends %>
     memcached_multi_commands.get_hits.label Get Hits
-    memcached_multi_commands.get_misses.sum <%= Chef::Munin.expand "%%:memcached_multi_commands.get_misses", @backends %>
+    memcached_multi_commands.get_misses.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.get_misses", @frontends %>
     memcached_multi_commands.get_misses.label Get Misses
-    memcached_multi_commands.delete_hits.sum <%= Chef::Munin.expand "%%:memcached_multi_commands.delete_hits", @backends %>
+    memcached_multi_commands.delete_hits.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.delete_hits", @frontends %>
     memcached_multi_commands.delete_hits.label Delete Hits
-    memcached_multi_commands.delete_misses.sum <%= Chef::Munin.expand "%%:memcached_multi_commands.delete_misses", @backends %>
+    memcached_multi_commands.delete_misses.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.delete_misses", @frontends %>
     memcached_multi_commands.delete_misses.label Delete Misses
-    memcached_multi_commands.incr_hits.sum <%= Chef::Munin.expand "%%:memcached_multi_commands.incr_hits", @backends %>
+    memcached_multi_commands.incr_hits.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.incr_hits", @frontends %>
     memcached_multi_commands.incr_hits.label Increment Hits
-    memcached_multi_commands.incr_misses.sum <%= Chef::Munin.expand "%%:memcached_multi_commands.incr_misses", @backends %>
+    memcached_multi_commands.incr_misses.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.incr_misses", @frontends %>
     memcached_multi_commands.incr_misses.label Increment Misses
-    memcached_multi_commands.decr_hits.sum <%= Chef::Munin.expand "%%:memcached_multi_commands.decr_hits", @backends %>
+    memcached_multi_commands.decr_hits.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.decr_hits", @frontends %>
     memcached_multi_commands.decr_hits.label Decrement Hits
-    memcached_multi_commands.decr_misses.sum <%= Chef::Munin.expand "%%:memcached_multi_commands.decr_misses", @backends %>
+    memcached_multi_commands.decr_misses.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.decr_misses", @frontends %>
     memcached_multi_commands.decr_misses.label Decrement Misses
-    memcached_multi_commands.touch_hits.sum <%= Chef::Munin.expand "%%:memcached_multi_commands.touch_hits", @backends %>
+    memcached_multi_commands.touch_hits.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.touch_hits", @frontends %>
     memcached_multi_commands.touch_hits.label Touch Hits
-    memcached_multi_commands.touch_misses.sum <%= Chef::Munin.expand "%%:memcached_multi_commands.touch_misses", @backends %>
+    memcached_multi_commands.touch_misses.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_commands.touch_misses", @frontends %>
     memcached_multi_commands.touch_misses.label Touch Misses
     memcached_multi_conns.graph_title Connections
     memcached_multi_conns.graph_vlabel Connections per ${graph_period}
     memcached_multi_conns.graph_category memcached
     memcached_multi_conns.graph_order max_conns curr_conns avg_conns
-    memcached_multi_conns.curr_conns.sum <%= Chef::Munin.expand "%%:memcached_multi_conns.curr_conns", @backends %>
+    memcached_multi_conns.curr_conns.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_conns.curr_conns", @frontends %>
     memcached_multi_conns.curr_conns.label Current Connections
-    memcached_multi_conns.max_conns.sum <%= Chef::Munin.expand "%%:memcached_multi_conns.max_conns", @backends %>
+    memcached_multi_conns.max_conns.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_conns.max_conns", @frontends %>
     memcached_multi_conns.max_conns.label Max Connections
-    memcached_multi_conns.avg_conns.sum <%= Chef::Munin.expand "%%:memcached_multi_conns.avg_conns", @backends %>
+    memcached_multi_conns.avg_conns.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_conns.avg_conns", @frontends %>
     memcached_multi_conns.avg_conns.label Avg Connections
     memcached_multi_evictions.graph_title Evictions
     memcached_multi_evictions.graph_vlabel Evictions per ${graph_period}
     memcached_multi_evictions.graph_category memcached
-    memcached_multi_evictions.evictions.sum <%= Chef::Munin.expand "%%:memcached_multi_evictions.evictions", @backends %>
+    memcached_multi_evictions.evictions.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_evictions.evictions", @frontends %>
     memcached_multi_evictions.evictions.label Evictions
-    memcached_multi_evictions.evicted_nonzero.sum <%= Chef::Munin.expand "%%:memcached_multi_evictions.evicted_nonzero", @backends %>
+    memcached_multi_evictions.evicted_nonzero.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_evictions.evicted_nonzero", @frontends %>
     memcached_multi_evictions.evicted_nonzero.label Evictions prior to Expire
-    memcached_multi_evictions.reclaimed.sum <%= Chef::Munin.expand "%%:memcached_multi_evictions.reclaimed", @backends %>
+    memcached_multi_evictions.reclaimed.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_evictions.reclaimed", @frontends %>
     memcached_multi_evictions.reclaimed.label Reclaimed Items
     memcached_multi_items.graph_title Items
     memcached_multi_items.graph_vlabel Items in Memcached
     memcached_multi_items.graph_category memcached
     memcached_multi_items.graph_order curr_items total_items
-    memcached_multi_items.curr_items.sum <%= Chef::Munin.expand "%%:memcached_multi_items.curr_items", @backends %>
+    memcached_multi_items.curr_items.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_items.curr_items", @frontends %>
     memcached_multi_items.curr_items.label Current Items
-    memcached_multi_items.total_items.sum <%= Chef::Munin.expand "%%:memcached_multi_items.total_items", @backends %>
+    memcached_multi_items.total_items.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_items.total_items", @frontends %>
     memcached_multi_items.total_items.label New Items
     memcached_multi_memory.graph_title Memory Usage
     memcached_multi_memory.graph_vlabel Bytes Used
     memcached_multi_memory.graph_category memcached
     memcached_multi_memory.graph_order limit_maxbytes bytes
-    memcached_multi_memory.limit_maxbytes.sum <%= Chef::Munin.expand "%%:memcached_multi_memory.limit_maxbytes", @backends %>
+    memcached_multi_memory.limit_maxbytes.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_memory.limit_maxbytes", @frontends %>
     memcached_multi_memory.limit_maxbytes.label Maximum Bytes Allocated
-    memcached_multi_memory.bytes.sum <%= Chef::Munin.expand "%%:memcached_multi_memory.bytes", @backends %>
+    memcached_multi_memory.bytes.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_memory.bytes", @frontends %>
     memcached_multi_memory.bytes.label Current Bytes Used
     memcached_multi_bytes.graph_title Network Traffic
     memcached_multi_bytes.graph_args --base 1000
     memcached_multi_bytes.graph_vlabel bits in (-) / out (+)
     memcached_multi_bytes.graph_category memcached
     memcached_multi_bytes.graph_order bytes_read bytes_written
-    memcached_multi_bytes.bytes_read.sum <%= Chef::Munin.expand "%%:memcached_multi_bytes.bytes_read", @backends %>
+    memcached_multi_bytes.bytes_read.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_bytes.bytes_read", @frontends %>
     memcached_multi_bytes.bytes_read.label Network Traffic coming in (-)
     memcached_multi_bytes.bytes_read.cdef bytes_read,8,*
     memcached_multi_bytes.bytes_read.graph no
-    memcached_multi_bytes.bytes_written.sum <%= Chef::Munin.expand "%%:memcached_multi_bytes.bytes_written", @backends %>
+    memcached_multi_bytes.bytes_written.sum <%= Chef::Munin.expand "%%name%%.openstreetmap.org:memcached_multi_bytes.bytes_written", @frontends %>
     memcached_multi_bytes.bytes_written.negative bytes_read
     memcached_multi_bytes.bytes_written.label Traffic in (-) / out (+)
     memcached_multi_bytes.bytes_written.cdef bytes_written,8,*
@@ -506,6 +510,17 @@ unknown_limit 144
     squid_byte_hitrates.<%= tc[:name].tr("-", "_") %>_hits.cdef <%= tc[:name].tr("-", "_") %>_hits,<%= tc[:name].tr("-", "_") %>_total,/,100,*
     squid_byte_hitrates.<%= tc[:name].tr("-", "_") %>_hits.label <%= tc[:name] %>
     squid_byte_hitrates.<%= tc[:name].tr("-", "_") %>_hits.draw LINE1
+<% end -%>
+    nginx_requests.graph_title Nginx requests
+    nginx_requests.graph_vlabel Requests per ${graph_period}
+    nginx_requests.graph_category nginx
+    nginx_requests.graph_order <%= Chef::Munin.expand "%%%name%%%=%%name%%.openstreetmap.org:nginx_request.request", @tilecaches %>
+    nginx_requests.graph_total total
+    nginx_requests.graph_args --lower-limit 0
+<% @tilecaches.each do |tc| -%>
+    nginx_requests.<%= tc[:name].tr("-", "_") %>.label <%= tc[:name] %>
+    nginx_requests.<%= tc[:name].tr("-", "_") %>.draw AREASTACK
+    nginx_requests.<%= tc[:name].tr("-", "_") %>.min 0
 <% end -%>
 <% end -%>
 <% unless @renderers.empty? -%>
index 516c38a41b88571e3e07e700beb4adffac7a6900..ec9743c946b964574cf8f8754c45435c7eed7b20 100644 (file)
@@ -85,7 +85,9 @@ module OpenStreetMap
     end
 
     def mysql_users
-      @mysql_users ||= query("SELECT * FROM user").each_with_object({}) do |user, users|
+      privilege_columns = USER_PRIVILEGES.collect { |privilege| "#{privilege}_priv" }.join(", ")
+
+      @mysql_users ||= query("SELECT user, host, #{privilege_columns} FROM user").each_with_object({}) do |user, users|
         name = "'#{user[:user]}'@'#{user[:host]}'"
 
         users[name] = USER_PRIVILEGES.each_with_object({}) do |privilege, privileges|
@@ -131,6 +133,12 @@ module OpenStreetMap
       case privilege
       when :grant
         "GRANT OPTION"
+      when :show_db
+        "SHOW DATABASES"
+      when :repl_slave
+        "REPLICATION SLAVE"
+      when :repl_client
+        "REPLICATION CLIENT"
       when :create_tmp_table
         "CREATE TEMPORARY TABLES"
       else
index 6dd2041bb304b602595ec0c3b00cacefebd82a76..4f94d6099054ac24e890392ace88f89cdb53229f 100644 (file)
@@ -6,4 +6,6 @@ description       "Installs and configures mysql"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "chef"
 depends           "munin"
+depends           "prometheus"
index bbbca3c616cfd6c91c2262dd19c47f5487c2a22c..d0d7b1679230c2448f0d7278c9207913923cf7ea 100644 (file)
@@ -17,6 +17,9 @@
 # limitations under the License.
 #
 
+include_recipe "munin"
+include_recipe "prometheus"
+
 package "mysql-server"
 package "mysql-client"
 
@@ -29,7 +32,7 @@ template "/etc/mysql/mysql.conf.d/zzz-chef.cnf" do
   source "my.cnf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[mysql]"
 end
 
@@ -57,3 +60,16 @@ end
     action :delete
   end
 end
+
+mysql_password = persistent_token("mysql", "prometheus", "password")
+
+mysql_user "prometheus" do
+  password mysql_password
+  process true
+  repl_client true
+end
+
+prometheus_exporter "mysqld" do
+  port 9104
+  environment "DATA_SOURCE_NAME" => "prometheus:#{mysql_password}@(localhost:3306)/"
+end
index be985f56381986cfc27072c6ec4591c8111c1159..65b6d2e224b14799ee593238473f9e8d0e32e8b3 100644 (file)
@@ -19,7 +19,7 @@
 
 default_action :create
 
-property :database, :kind_of => String, :name_attribute => true
+property :database, :kind_of => String, :name_property => true
 property :permissions, :kind_of => Hash, :default => {}
 
 action :create do
index 13e344966517418ad79825429cbc52233608529f..078316fc815ed75d4319e430fee4472cb3e6f5a8 100644 (file)
@@ -19,7 +19,7 @@
 
 default_action :create
 
-property :user, :kind_of => String, :name_attribute => true
+property :user, :kind_of => String, :name_property => true
 property :password, :kind_of => String
 
 OpenStreetMap::MySQL::USER_PRIVILEGES.each do |privilege|
index f7db87730f14ded5b8d719defc7f30957d654a12..8d369de4b55e2533188ebb6d0020b62618a85e29 100644 (file)
@@ -1,3 +1,4 @@
+default[:networking][:firewall][:enabled] = true
 default[:networking][:firewall][:inet] = []
 default[:networking][:firewall][:inet6] = []
 default[:networking][:firewall][:http_rate_limit] = "-"
@@ -6,6 +7,12 @@ default[:networking][:firewall][:log] = true
 default[:networking][:firewall][:mark] = true
 default[:networking][:firewall][:raw] = true
 default[:networking][:firewall][:mangle] = true
+default[:networking][:roles] = {}
 default[:networking][:interfaces] = {}
-default[:networking][:nameservers] = []
+default[:networking][:nameservers] = %w[1.1.1.1 1.0.0.1 2606:4700:4700::1111 2606:4700:4700::1001]
 default[:networking][:search] = []
+default[:networking][:dnssec] = "allow-downgrade"
+default[:networking][:hostname] = node.name
+default[:networking][:wireguard][:enabled] = true
+default[:networking][:wireguard][:keepalive] = false
+default[:networking][:wireguard][:peers] = []
diff --git a/cookbooks/networking/definitions/firewall_rule.rb b/cookbooks/networking/definitions/firewall_rule.rb
deleted file mode 100644 (file)
index 0196c41..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Cookbook:: networking
-# Definition:: firewall_rule
-#
-# Copyright:: 2011, OpenStreetMap Foundation
-#
-# 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
-#
-#     https://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.
-#
-
-define :firewall_rule, :action => :accept do
-  rule = Hash[
-    :action => params[:action].to_s.upcase,
-    :source => params[:source],
-    :dest => params[:dest],
-    :proto => params[:proto],
-    :dest_ports => params[:dest_ports] || "-",
-    :source_ports => params[:source_ports] || "-",
-    :rate_limit => params[:rate_limit] || "-",
-    :connection_limit => params[:connection_limit] || "-",
-    :helper => params[:helper] || "-"
-  ]
-
-  if params[:family].nil?
-    node.default[:networking][:firewall][:inet] << rule
-    node.default[:networking][:firewall][:inet6] << rule
-  elsif params[:family].to_s == "inet"
-    node.default[:networking][:firewall][:inet] << rule
-  elsif params[:family].to_s == "inet6"
-    node.default[:networking][:firewall][:inet6] << rule
-  else
-    log "Unsupported network family" do
-      level :error
-    end
-  end
-end
index d31d885f995076af73eef0d034023e4f5a97cb07..67c89d052192e6574df873751e3a44ea63b42d99 100644 (file)
@@ -6,6 +6,8 @@ class Chef
       interfaces(options).each do |interface|
         address = interface[:public_address] || interface[:address]
 
+        next if address.nil?
+
         if block.nil?
           addresses << address
         else
@@ -16,12 +18,12 @@ class Chef
       addresses
     end
 
-    def internal_ipaddress
-      ipaddresses(:role => :internal).first
+    def internal_ipaddress(options = {})
+      ipaddresses(options.merge(:role => :internal)).first
     end
 
-    def external_ipaddress
-      ipaddresses(:role => :external).first
+    def external_ipaddress(options = {})
+      ipaddresses(options.merge(:role => :external)).first
     end
   end
 end
index 3d2944c1555e8fe0bad7da8125dbcba30cebf282..c37012709faf15c9ef5d126c3153770ca8b6d3d2 100644 (file)
@@ -5,5 +5,4 @@ license           "Apache-2.0"
 description       "Configures networking"
 
 version           "1.0.0"
-
-supports          "ubuntu"
+depends           "chef"
index dfa73f196c5aa909e3203a5c20bb81c405aca570..c24686d0b0344a2a968b8001d6a28b96f27371c4 100644 (file)
 require "ipaddr"
 require "yaml"
 
+keys = data_bag_item("networking", "keys")
+
+package "netplan.io"
+
 netplan = {
   "network" => {
     "version" => 2,
@@ -37,18 +41,21 @@ node[:networking][:interfaces].each do |name, interface|
   if interface[:interface]
     if interface[:role] && (role = node[:networking][:roles][interface[:role]])
       if role[interface[:family]]
-        node.normal[:networking][:interfaces][name][:prefix] = role[interface[:family]][:prefix]
-        node.normal[:networking][:interfaces][name][:gateway] = role[interface[:family]][:gateway]
+        node.default[:networking][:interfaces][name][:prefix] = role[interface[:family]][:prefix]
+        node.default[:networking][:interfaces][name][:gateway] = role[interface[:family]][:gateway]
+        node.default[:networking][:interfaces][name][:routes] = role[interface[:family]][:routes]
       end
 
-      node.normal[:networking][:interfaces][name][:metric] = role[:metric]
-      node.normal[:networking][:interfaces][name][:zone] = role[:zone]
+      node.default[:networking][:interfaces][name][:metric] = role[:metric]
+      node.default[:networking][:interfaces][name][:zone] = role[:zone]
     end
 
-    prefix = node[:networking][:interfaces][name][:prefix]
+    if interface[:address]
+      prefix = node[:networking][:interfaces][name][:prefix]
 
-    node.normal[:networking][:interfaces][name][:netmask] = (~IPAddr.new(interface[:address]).mask(0)).mask(prefix)
-    node.normal[:networking][:interfaces][name][:network] = IPAddr.new(interface[:address]).mask(prefix)
+      node.default[:networking][:interfaces][name][:netmask] = (~IPAddr.new(interface[:address]).mask(0)).mask(prefix)
+      node.default[:networking][:interfaces][name][:network] = IPAddr.new(interface[:address]).mask(prefix)
+    end
 
     interface = node[:networking][:interfaces][name]
 
@@ -74,7 +81,9 @@ node[:networking][:interfaces].each do |name, interface|
                    }
                  end
 
-    deviceplan["addresses"].push("#{interface[:address]}/#{prefix}")
+    if interface[:address]
+      deviceplan["addresses"].push("#{interface[:address]}/#{prefix}")
+    end
 
     if interface[:mtu]
       deviceplan["mtu"] = interface[:mtu]
@@ -124,6 +133,22 @@ node[:networking][:interfaces].each do |name, interface|
         )
       end
     end
+
+    if interface[:routes]
+      interface[:routes].each do |to, parameters|
+        next if parameters[:via] == interface[:address]
+
+        route = {
+          "to" => to
+        }
+
+        route["type"] = parameters[:type] if parameters[:type]
+        route["via"] = parameters[:via] if parameters[:via]
+        route["metric"] = parameters[:metric] if parameters[:metric]
+
+        deviceplan["routes"].push(route)
+      end
+    end
   else
     node.rm(:networking, :interfaces, name)
   end
@@ -152,7 +177,7 @@ end
 file "/etc/netplan/99-chef.yaml" do
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   content YAML.dump(netplan)
 end
 
@@ -160,24 +185,143 @@ package "cloud-init" do
   action :purge
 end
 
-execute "hostname" do
+if node[:networking][:wireguard][:enabled]
+  wireguard_id = persistent_token("networking", "wireguard")
+
+  node.default[:networking][:wireguard][:address] = "fd43:e709:ea6d:1:#{wireguard_id[0, 4]}:#{wireguard_id[4, 4]}:#{wireguard_id[8, 4]}:#{wireguard_id[12, 4]}"
+
+  package "wireguard-tools" do
+    compile_time true
+  end
+
+  directory "/var/lib/systemd/wireguard" do
+    owner "root"
+    group "systemd-network"
+    mode "750"
+    compile_time true
+  end
+
+  file "/var/lib/systemd/wireguard/private.key" do
+    action :create_if_missing
+    owner "root"
+    group "systemd-network"
+    mode "640"
+    content %x(wg genkey)
+    compile_time true
+  end
+
+  node.default[:networking][:wireguard][:public_key] = %x(wg pubkey < /var/lib/systemd/wireguard/private.key).chomp
+
+  file "/var/lib/systemd/wireguard/preshared.key" do
+    action :create_if_missing
+    owner "root"
+    group "systemd-network"
+    mode "640"
+    content keys["wireguard"]
+  end
+
+  if node[:roles].include?("gateway")
+    search(:node, "roles:gateway") do |gateway|
+      next if gateway.name == node.name
+      next unless gateway[:networking][:wireguard] && gateway[:networking][:wireguard][:enabled]
+
+      allowed_ips = gateway.interfaces(:role => :internal).map do |interface|
+        "#{interface[:network]}/#{interface[:prefix]}"
+      end
+
+      node.default[:networking][:wireguard][:peers] << {
+        :public_key => gateway[:networking][:wireguard][:public_key],
+        :allowed_ips => allowed_ips,
+        :endpoint => "#{gateway.name}:51820"
+      }
+    end
+
+    search(:node, "roles:mail OR roles:prometheus") do |server|
+      allowed_ips = server.interfaces(:role => :internal).map do |interface|
+        "#{interface[:network]}/#{interface[:prefix]}"
+      end
+
+      if server[:networking][:private_address]
+        allowed_ips << "#{server[:networking][:private_address]}/32"
+      end
+
+      node.default[:networking][:wireguard][:peers] << {
+        :public_key => server[:networking][:wireguard][:public_key],
+        :allowed_ips => allowed_ips,
+        :endpoint => "#{server.name}:51820"
+      }
+    end
+
+    node.default[:networking][:wireguard][:peers] << {
+      :public_key => "7Oj9ufNlgidyH/xDc+aHQKMjJPqTmD/ab13agMh6AxA=",
+      :allowed_ips => "10.0.16.1/32",
+      :endpoint => "gate.compton.nu:51820"
+    }
+  end
+
+  template "/etc/systemd/network/wireguard.netdev" do
+    source "wireguard.netdev.erb"
+    owner "root"
+    group "systemd-network"
+    mode "640"
+  end
+
+  template "/etc/systemd/network/wireguard.network" do
+    source "wireguard.network.erb"
+    owner "root"
+    group "root"
+    mode "644"
+  end
+
+  if node[:lsb][:release].to_f < 20.04
+    execute "ip-link-delete-wg0" do
+      action :nothing
+      command "ip link delete wg0"
+      subscribes :run, "template[/etc/systemd/network/wireguard.netdev]"
+      only_if { ::File.exist?("/sys/class/net/wg0") }
+    end
+
+    service "systemd-networkd" do
+      action :nothing
+      subscribes :restart, "template[/etc/systemd/network/wireguard.netdev]"
+      subscribes :restart, "template[/etc/systemd/network/wireguard.network]"
+      not_if { ENV.key?("TEST_KITCHEN") }
+    end
+  else
+    execute "networkctl-delete-wg0" do
+      action :nothing
+      command "networkctl delete wg0"
+      subscribes :run, "template[/etc/systemd/network/wireguard.netdev]"
+      only_if { ::File.exist?("/sys/class/net/wg0") }
+    end
+
+    execute "networkctl-reload" do
+      action :nothing
+      command "networkctl reload"
+      subscribes :run, "template[/etc/systemd/network/wireguard.netdev]"
+      subscribes :run, "template[/etc/systemd/network/wireguard.network]"
+      not_if { ENV.key?("TEST_KITCHEN") }
+    end
+  end
+end
+
+ohai "reload-hostname" do
   action :nothing
-  command "/bin/hostname -F /etc/hostname"
+  plugin "hostname"
 end
 
-template "/etc/hostname" do
-  source "hostname.erb"
-  owner "root"
-  group "root"
-  mode 0o644
-  notifies :run, "execute[hostname]"
+execute "hostnamectl-set-hostname" do
+  command "hostnamectl set-hostname #{node[:networking][:hostname]}"
+  notifies :reload, "ohai[reload-hostname]"
+  not_if { ENV.key?("TEST_KITCHEN") || node[:hostnamectl][:static_hostname] == node[:networking][:hostname] }
 end
 
 template "/etc/hosts" do
   source "hosts.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
+  not_if { ENV["TEST_KITCHEN"] }
 end
 
 service "systemd-resolved" do
@@ -187,54 +331,25 @@ end
 directory "/etc/systemd/resolved.conf.d" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 template "/etc/systemd/resolved.conf.d/99-chef.conf" do
   source "resolved.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
-  notifies :restart, "service[systemd-resolved]"
+  mode "644"
+  notifies :restart, "service[systemd-resolved]", :immediately
 end
 
-if node[:networking][:tcp_fastopen_key]
-  fastopen_keys = data_bag_item("networking", "fastopen")
-
-  node.normal[:sysctl][:tcp_fastopen] = {
-    :comment => "Set shared key for TCP fast open",
-    :parameters => {
-      "net.ipv4.tcp_fastopen_key" => fastopen_keys[node[:networking][:tcp_fastopen_key]]
-    }
-  }
+if node[:filesystem][:by_mountpoint][:"/etc/resolv.conf"]
+  execute "umount-resolve-conf" do
+    command "umount -c /etc/resolv.conf"
+  end
 end
 
-node.interfaces(:role => :internal) do |interface|
-  if interface[:gateway] && interface[:gateway] != interface[:address]
-    search(:node, "networking_interfaces*address:#{interface[:gateway]}") do |gateway|
-      next unless gateway[:openvpn]
-
-      gateway[:openvpn][:tunnels].each_value do |tunnel|
-        if tunnel[:peer][:address]
-          route tunnel[:peer][:address] do
-            netmask "255.255.255.255"
-            gateway interface[:gateway]
-            device interface[:interface]
-          end
-        end
-
-        next unless tunnel[:peer][:networks]
-
-        tunnel[:peer][:networks].each do |network|
-          route network[:address] do
-            netmask network[:netmask]
-            gateway interface[:gateway]
-            device interface[:interface]
-          end
-        end
-      end
-    end
-  end
+link "/etc/resolv.conf" do
+  to "../run/systemd/resolve/stub-resolv.conf"
 end
 
 zones = {}
@@ -257,7 +372,7 @@ template "/etc/default/shorewall" do
   source "shorewall-default.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[shorewall]"
 end
 
@@ -265,7 +380,7 @@ template "/etc/shorewall/shorewall.conf" do
   source "shorewall.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[shorewall]"
 end
 
@@ -273,7 +388,7 @@ template "/etc/shorewall/zones" do
   source "shorewall-zones.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   variables :type => "ipv4"
   notifies :restart, "service[shorewall]"
 end
@@ -282,7 +397,7 @@ template "/etc/shorewall/interfaces" do
   source "shorewall-interfaces.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[shorewall]"
 end
 
@@ -290,7 +405,7 @@ template "/etc/shorewall/hosts" do
   source "shorewall-hosts.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   variables :zones => zones
   notifies :restart, "service[shorewall]"
 end
@@ -299,7 +414,7 @@ template "/etc/shorewall/conntrack" do
   source "shorewall-conntrack.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[shorewall]"
   only_if { node[:networking][:firewall][:raw] }
 end
@@ -308,7 +423,7 @@ template "/etc/shorewall/policy" do
   source "shorewall-policy.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[shorewall]"
 end
 
@@ -316,22 +431,32 @@ template "/etc/shorewall/rules" do
   source "shorewall-rules.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   variables :family => "inet"
   notifies :restart, "service[shorewall]"
 end
 
-service "shorewall" do
-  action [:enable, :start]
-  supports :restart => true
-  status_command "shorewall status"
+if node[:networking][:firewall][:enabled]
+  service "shorewall" do
+    action [:enable, :start]
+    supports :restart => true
+    status_command "shorewall status"
+    ignore_failure true
+  end
+else
+  service "shorewall" do
+    action [:disable, :stop]
+    supports :restart => true
+    status_command "shorewall status"
+    ignore_failure true
+  end
 end
 
 template "/etc/logrotate.d/shorewall" do
   source "logrotate.shorewall.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   variables :name => "shorewall"
 end
 
@@ -345,14 +470,20 @@ firewall_rule "limit-icmp-echo" do
   rate_limit "s:1/sec:5"
 end
 
-%w[ucl ams bm].each do |zone|
-  firewall_rule "accept-openvpn-#{zone}" do
+if node[:networking][:wireguard][:enabled]
+  wireguard_source = if node[:roles].include?("gateway")
+                       "net"
+                     else
+                       "osm"
+                     end
+
+  firewall_rule "accept-wireguard" do
     action :accept
-    source zone
+    source wireguard_source
     dest "fw"
     proto "udp"
-    dest_ports "1194:1197"
-    source_ports "1194:1197"
+    dest_ports "51820"
+    source_ports "51820"
   end
 end
 
@@ -361,7 +492,7 @@ if node[:roles].include?("gateway")
     source "shorewall-masq.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     notifies :restart, "service[shorewall]"
   end
 else
@@ -378,7 +509,7 @@ unless node.interfaces(:family => :inet6).empty?
     source "shorewall-default.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     notifies :restart, "service[shorewall6]"
   end
 
@@ -386,7 +517,7 @@ unless node.interfaces(:family => :inet6).empty?
     source "shorewall6.conf.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     notifies :restart, "service[shorewall6]"
   end
 
@@ -394,7 +525,7 @@ unless node.interfaces(:family => :inet6).empty?
     source "shorewall-zones.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables :type => "ipv6"
     notifies :restart, "service[shorewall6]"
   end
@@ -403,7 +534,7 @@ unless node.interfaces(:family => :inet6).empty?
     source "shorewall6-interfaces.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     notifies :restart, "service[shorewall6]"
   end
 
@@ -411,7 +542,7 @@ unless node.interfaces(:family => :inet6).empty?
     source "shorewall6-hosts.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables :zones => zones
     notifies :restart, "service[shorewall6]"
   end
@@ -420,7 +551,7 @@ unless node.interfaces(:family => :inet6).empty?
     source "shorewall-conntrack.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     notifies :restart, "service[shorewall6]"
     only_if { node[:networking][:firewall][:raw] }
   end
@@ -429,7 +560,7 @@ unless node.interfaces(:family => :inet6).empty?
     source "shorewall-policy.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     notifies :restart, "service[shorewall6]"
   end
 
@@ -437,22 +568,32 @@ unless node.interfaces(:family => :inet6).empty?
     source "shorewall-rules.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables :family => "inet6"
     notifies :restart, "service[shorewall6]"
   end
 
-  service "shorewall6" do
-    action [:enable, :start]
-    supports :restart => true
-    status_command "shorewall6 status"
+  if node[:networking][:firewall][:enabled]
+    service "shorewall6" do
+      action [:enable, :start]
+      supports :restart => true
+      status_command "shorewall6 status"
+      ignore_failure true
+    end
+  else
+    service "shorewall6" do
+      action [:disable, :stop]
+      supports :restart => true
+      status_command "shorewall6 status"
+      ignore_failure true
+    end
   end
 
   template "/etc/logrotate.d/shorewall6" do
     source "logrotate.shorewall.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables :name => "shorewall6"
   end
 
diff --git a/cookbooks/networking/resources/firewall_rule.rb b/cookbooks/networking/resources/firewall_rule.rb
new file mode 100644 (file)
index 0000000..e92681e
--- /dev/null
@@ -0,0 +1,77 @@
+#
+# Cookbook:: networking
+# Resource:: firewall_rule
+#
+# Copyright:: 2020, OpenStreetMap Foundation
+#
+# 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
+#
+#     https://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.
+#
+
+resource_name :firewall_rule
+provides :firewall_rule
+
+default_action :nothing
+
+property :rule, :kind_of => String, :name_property => true
+property :family, :kind_of => [String, Symbol]
+property :source, :kind_of => String, :required => true
+property :dest, :kind_of => String, :required => true
+property :proto, :kind_of => String, :required => true
+property :dest_ports, :kind_of => [String, Integer], :default => "-"
+property :source_ports, :kind_of => [String, Integer], :default => "-"
+property :rate_limit, :kind_of => String, :default => "-"
+property :connection_limit, :kind_of => [String, Integer], :default => "-"
+property :helper, :kind_of => String, :default => "-"
+
+property :compile_time, TrueClass, :default => true
+
+action :accept do
+  add_rule :accept
+end
+
+action :drop do
+  add_rule :drop
+end
+
+action :reject do
+  add_rule :reject
+end
+
+action_class do
+  def add_rule(action)
+    rule = {
+      :action => action.to_s.upcase,
+      :source => new_resource.source,
+      :dest => new_resource.dest,
+      :proto => new_resource.proto,
+      :dest_ports => new_resource.dest_ports.to_s,
+      :source_ports => new_resource.source_ports.to_s,
+      :rate_limit => new_resource.rate_limit,
+      :connection_limit => new_resource.connection_limit.to_s,
+      :helper => new_resource.helper
+    }
+
+    if new_resource.family.nil?
+      node.default[:networking][:firewall][:inet] << rule
+      node.default[:networking][:firewall][:inet6] << rule
+    elsif new_resource.family.to_s == "inet"
+      node.default[:networking][:firewall][:inet] << rule
+    elsif new_resource.family.to_s == "inet6"
+      node.default[:networking][:firewall][:inet6] << rule
+    else
+      log "Unsupported network family" do
+        level :error
+      end
+    end
+  end
+end
diff --git a/cookbooks/networking/templates/default/hostname.erb b/cookbooks/networking/templates/default/hostname.erb
deleted file mode 100644 (file)
index 9842667..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<%= node[:fqdn] %>
index f749388efeb216505933b5557fb337dc2a342309..d57e78828ff1674412cf954c770d66c5d01d702f 100644 (file)
@@ -1,4 +1,5 @@
 [Resolve]
 DNS=<%= node[:networking][:nameservers].join(" ") %>
+FallbackDNS=1.1.1.1 9.9.9.10 8.8.8.8 2606:4700:4700::1111 2620:fe::10 2001:4860:4860::8888
 Domains=<%= node[:networking][:search].join(" ") %>
-DNSSEC=allow-downgrade
+DNSSEC=<%= node[:networking][:dnssec] %>
index 4701b9641cc20540a1d90c4c53b316996f9d7737..b6a7217270e226731eb789a0492f37ad72502f83 100644 (file)
@@ -12,4 +12,4 @@ net   <%= interface[:interface] %>            nosmurfs,tcpflags
 <% end -%>
 <% end -%>
 <% end -%>
-loc    tun+            nosmurfs,tcpflags
+loc    wg+             nosmurfs,tcpflags
index b91e46f30c33f3bf84aab25800f5e96a026f52c5..d3d403c95ab17135a91d377b0279a784acdad5d5 100644 (file)
@@ -6,38 +6,5 @@ loc            <%= @type %>
 net            <%= @type %>
 osm:net                <%= @type %>
 ucl:osm                <%= @type %>
-ic:osm         <%= @type %>
 ams:osm                <%= @type %>
 bm:osm         <%= @type %>
-ts:osm         <%= @type %>
-yx:osm         <%= @type %>
-ra:osm         <%= @type %>
-pa:osm         <%= @type %>
-bx:osm         <%= @type %>
-ff:osm         <%= @type %>
-pr:osm         <%= @type %>
-ly:osm         <%= @type %>
-ov:osm         <%= @type %>
-hz:osm         <%= @type %>
-bh:osm         <%= @type %>
-dt:osm         <%= @type %>
-nc:osm         <%= @type %>
-ool:osm                <%= @type %>
-cnt:osm                <%= @type %>
-jn:osm         <%= @type %>
-es:osm         <%= @type %>
-sz:osm         <%= @type %>
-ex:osm         <%= @type %>
-dh:osm         <%= @type %>
-aws:osm                <%= @type %>
-ds:osm         <%= @type %>
-uz:osm          <%= @type %>
-ovh:osm         <%= @type %>
-ffr:osm         <%= @type %>
-ixz:osm         <%= @type %>
-grn:osm         <%= @type %>
-g5s:osm         <%= @type %>
-na:osm          <%= @type %>
-tnn:osm         <%= @type %>
-av:osm          <%= @type %>
-grf:osm         <%= @type %>
diff --git a/cookbooks/networking/templates/default/wireguard.netdev.erb b/cookbooks/networking/templates/default/wireguard.netdev.erb
new file mode 100644 (file)
index 0000000..7866f97
--- /dev/null
@@ -0,0 +1,28 @@
+[NetDev]
+Name=wg0
+Kind=wireguard
+
+[WireGuard]
+<% if node[:lsb][:release].to_f < 20.04 -%>
+PrivateKey=<%= IO.read("/var/lib/systemd/wireguard/private.key").chomp %>
+<% else -%>
+PrivateKeyFile=/var/lib/systemd/wireguard/private.key
+<% end -%>
+ListenPort=51820
+<% node[:networking][:wireguard][:peers].each do |peer| -%>
+
+[WireGuardPeer]
+PublicKey=<%= peer[:public_key] %>
+<% if node[:lsb][:release].to_f < 20.04 -%>
+PresharedKey=<%= IO.read("/var/lib/systemd/wireguard/preshared.key").chomp %>
+<% else -%>
+PresharedKeyFile=/var/lib/systemd/wireguard/preshared.key
+<% end -%>
+AllowedIPs=<%= Array(peer[:allowed_ips]).sort.join(",") %>
+<% if peer[:endpoint] -%>
+Endpoint=<%= peer[:endpoint] %>
+<% end -%>
+<% if node[:networking][:wireguard][:keepalive] -%>
+PersistentKeepalive=<%= node[:networking][:wireguard][:keepalive] %>
+<% end -%>
+<% end -%>
diff --git a/cookbooks/networking/templates/default/wireguard.network.erb b/cookbooks/networking/templates/default/wireguard.network.erb
new file mode 100644 (file)
index 0000000..5e215b1
--- /dev/null
@@ -0,0 +1,23 @@
+[Match]
+Name=wg0
+
+[Network]
+<% if node.internal_ipaddress -%>
+Address=<%= node.internal_ipaddress %>/32
+<% end -%>
+<% if node[:networking][:private_address] -%>
+Address=<%= node[:networking][:private_address] %>/32
+<% end -%>
+Address=<%= node[:networking][:wireguard][:address] %>/128
+
+[Route]
+Destination=fd43:e709:ea6d:1::/64
+<% node[:networking][:wireguard][:peers].each do |peer| -%>
+<% Array(peer[:allowed_ips]).sort.each do |ip| -%>
+<% unless ip =~ /^fd43:e709:ea6d:1::/ -%>
+
+[Route]
+Destination=<%= ip %>
+<% end -%>
+<% end -%>
+<% end -%>
diff --git a/cookbooks/nfs/attributes/default.rb b/cookbooks/nfs/attributes/default.rb
new file mode 100644 (file)
index 0000000..f3b1761
--- /dev/null
@@ -0,0 +1 @@
+default[:nfs] = {}
index 80d3d9e21cb7dc1f7e6f4c785c9d39c2c4c3b2d5..216e825f2b48b6776587705d8f891267d4b41843 100644 (file)
@@ -29,9 +29,9 @@ node[:nfs].each do |mountpoint, details|
   directory mountpoint do
     owner "root"
     group "root"
-    mode 0o755
+    mode "755"
     recursive true
-    not_if { File.exist?(mountpoint) }
+    not_if { ::File.exist?(mountpoint) }
   end
 
   mount mountpoint do
index 0378075fdb37c313af9b125e9035d09db12a0a19..93fad876c707d99ebb17c4bbdf4989a0ce41b74d 100644 (file)
@@ -56,7 +56,7 @@ template "/etc/exports" do
   source "exports.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   variables :exports => exports
   notifies :run, "execute[exportfs]"
 end
index 44fb5bc10339d71a7f3a8a57a1c3b5dd69426ef1..21d22045bc60841f1e453369a6ffff924d97456e 100644 (file)
@@ -3,12 +3,17 @@ default[:nginx][:access_log] = "/var/log/nginx/access.log"
 
 # Tuning for nginx fastcgi cache zone
 default[:nginx][:cache][:fastcgi][:enable] = false
-default[:nginx][:cache][:fastcgi][:keys_zone] = "fastcgi_cache_zone:32M"
+default[:nginx][:cache][:fastcgi][:directory] = "/var/cache/nginx/fastcgi-cache"
+default[:nginx][:cache][:fastcgi][:keys_zone] = "fastcgi_cache_zone:48M"
 default[:nginx][:cache][:fastcgi][:inactive] = "45d"
-default[:nginx][:cache][:fastcgi][:max_size] = "2048M"
+default[:nginx][:cache][:fastcgi][:max_size] = "8192M"
 
 # Tuning for nginx proxy cache zone
 default[:nginx][:cache][:proxy][:enable] = false
-default[:nginx][:cache][:proxy][:keys_zone] = "proxy_cache_zone:32M"
+default[:nginx][:cache][:proxy][:directory] = "/var/cache/nginx/proxy-cache"
+default[:nginx][:cache][:proxy][:keys_zone] = "proxy_cache_zone:128M"
 default[:nginx][:cache][:proxy][:inactive] = "45d"
-default[:nginx][:cache][:proxy][:max_size] = "2048M"
+default[:nginx][:cache][:proxy][:max_size] = "16384M"
+
+# Enable nginx repository
+default[:apt][:sources] = node[:apt][:sources] | ["nginx"]
index edd5573b0753883092ecbce1af97f2396827509d..cd321f6daceaceb7013b0c8b22aba1b9f9600821 100644 (file)
@@ -6,4 +6,8 @@ description       "Installs and configures nginx"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "apt"
+depends           "munin"
+depends           "networking"
+depends           "prometheus"
 depends           "ssl"
index 95c9f8b17cdfc5664fd58aeb31a97a7b8359388a..d215e51c82a7176bc565fc00deab209587c20ce6 100644 (file)
 # limitations under the License.
 #
 
-package "nginx"
+include_recipe "apt"
+include_recipe "munin"
+include_recipe "prometheus"
+include_recipe "ssl"
 
-resolvers = node[:networking][:nameservers].map do |resolver|
-  IPAddr.new(resolver).ipv6? ? "[#{resolver}]" : resolver
-end
+package "nginx"
 
 template "/etc/nginx/nginx.conf" do
   source "nginx.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
-  variables :resolvers => resolvers
+  mode "644"
 end
 
-directory "/var/cache/nginx/fastcgi-cache" do
+directory node[:nginx][:cache][:fastcgi][:directory] do
   owner "www-data"
   group "root"
-  mode 0o755
+  mode "755"
+  recursive true
   only_if { node[:nginx][:cache][:fastcgi][:enable] }
 end
 
-directory "/var/cache/nginx/proxy-cache" do
+directory node[:nginx][:cache][:proxy][:directory] do
   owner "www-data"
   group "root"
-  mode 0o755
+  mode "755"
+  recursive true
   only_if { node[:nginx][:cache][:proxy][:enable] }
 end
 
@@ -50,3 +52,31 @@ service "nginx" do
   supports :status => true, :restart => true, :reload => true
   subscribes :restart, "template[/etc/nginx/nginx.conf]"
 end
+
+munin_plugin_conf "nginx" do
+  template "munin.erb"
+end
+
+package "libwww-perl"
+
+munin_plugin "nginx_request"
+munin_plugin "nginx_status"
+
+prometheus_exporter "nginx" do
+  port 9113
+  options "--nginx.scrape-uri=http://localhost:8050/nginx_status"
+end
+
+template "/usr/local/bin/nginx-old-cache-cleanup" do
+  source "nginx-old-cache-cleanup.erb"
+  owner "root"
+  group "root"
+  mode "755"
+end
+
+cron_d "nginx-old-cache-cleanup" do
+  minute "15"
+  hour "23"
+  user "www-data"
+  command "/usr/bin/timeout 6h /usr/local/bin/nginx-old-cache-cleanup"
+end
index 5ebaca69b4f49868e683435dad52066545850aab..45422434a9274b66d0b69a501361cc8c153a8f93 100644 (file)
 
 default_action :create
 
-property :site, :kind_of => String, :name_attribute => true
+property :site, :kind_of => String, :name_property => true
 property :directory, :kind_of => String
 property :cookbook, :kind_of => String
-property :template, :kind_of => String, :required => true
+property :template, :kind_of => String, :required => [:create]
 property :variables, :kind_of => Hash, :default => {}
-property :restart_nginx, :kind_of => [TrueClass, FalseClass], :default => true
 
 action :create do
   declare_resource :template, conf_path do
@@ -32,7 +31,7 @@ action :create do
     source new_resource.template
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables new_resource.variables.merge(:name => new_resource.site, :directory => directory)
   end
 end
@@ -40,6 +39,7 @@ end
 action :delete do
   file conf_path do
     action :delete
+    notifies :reload, "service[nginx]"
   end
 end
 
@@ -54,5 +54,5 @@ action_class do
 end
 
 def after_created
-  notifies :restart, "service[nginx]" if restart_nginx
+  notifies :reload, "service[nginx]"
 end
diff --git a/cookbooks/nginx/templates/default/munin.erb b/cookbooks/nginx/templates/default/munin.erb
new file mode 100644 (file)
index 0000000..56a2eff
--- /dev/null
@@ -0,0 +1,2 @@
+[nginx*]
+  env.url http://localhost:8050/nginx_status
diff --git a/cookbooks/nginx/templates/default/nginx-old-cache-cleanup.erb b/cookbooks/nginx/templates/default/nginx-old-cache-cleanup.erb
new file mode 100644 (file)
index 0000000..a67931b
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+set -e
+/usr/bin/renice -n 19 $$ >/dev/null
+/usr/bin/ionice -c 3 -p $$ >/dev/null
+[[ -d "/var/cache/nginx/fastcgi-cache" ]] && /usr/bin/find /var/cache/nginx/fastcgi-cache/?/??/ -maxdepth 1 -type f -delete 2>/dev/null || /bin/true
+[[ -d "/var/cache/nginx/fastcgi-cache" ]] && /usr/bin/find /var/cache/nginx/fastcgi-cache/ -maxdepth 2 -mindepth 2 -type d -wholename '*/?/??' -delete
+[[ -d "/var/cache/nginx/fastcgi-cache" ]] && /usr/bin/find /var/cache/nginx/fastcgi-cache/ -maxdepth 1 -mindepth 1 -type d -wholename '*/?' -delete
+[[ -d "/var/cache/nginx/proxy-cache" ]] && /usr/bin/find /var/cache/nginx/proxy-cache/?/??/ -maxdepth 1 -type f -delete 2>/dev/null || /bin/true
+[[ -d "/var/cache/nginx/proxy-cache" ]] && /usr/bin/find /var/cache/nginx/proxy-cache/ -maxdepth 2 -mindepth 2 -type d -wholename '*/?/??' -delete
+[[ -d "/var/cache/nginx/proxy-cache" ]] && /usr/bin/find /var/cache/nginx/proxy-cache/ -maxdepth 1 -mindepth 1 -type d -wholename '*/?' -delete
index e5969ce45ce3acb67f226c4f3a2ab5341851704c..f5d4fc26904e22bb9544b8c34a4104b7a974cf69 100644 (file)
@@ -25,12 +25,12 @@ http {
                       '$status $body_bytes_sent "$http_referer" '
                       '"$http_user_agent" "$http_x_forwarded_for"';
 
-    access_log  <%= node[:nginx][:access_log] %>  main  buffer=32k flush=1m;
+    access_log  <%= node[:nginx][:access_log] %>  main buffer=256k flush=1m;
 <% else -%>
     access_log  off;
 <% end -%>
 
-    keepalive_timeout  30;
+    keepalive_timeout 20 20;
 
     server_tokens off;
 
@@ -47,15 +47,27 @@ http {
     ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
 
     ssl_dhparam /etc/ssl/certs/dhparam.pem;
-    resolver <%= @resolvers.join(" ") %>;
+    resolver 127.0.0.53 ipv6=off;
     resolver_timeout 5s;
 
     <% if node['nginx']['cache']['fastcgi']['enable'] -%>
-    fastcgi_cache_path /var/cache/nginx/fastcgi-cache levels=1:2 keys_zone=<%= node['nginx']['cache']['fastcgi']['keys_zone'] %> inactive=<%= node['nginx']['cache']['fastcgi']['inactive'] %> max_size=<%= node['nginx']['cache']['fastcgi']['max_size'] %>;
+    fastcgi_cache_path <%= node['nginx']['cache']['fastcgi']['directory'] %> levels=2:2:2 use_temp_path=off keys_zone=<%= node['nginx']['cache']['fastcgi']['keys_zone'] %> inactive=<%= node['nginx']['cache']['fastcgi']['inactive'] %> max_size=<%= node['nginx']['cache']['fastcgi']['max_size'] %>;
     <% end -%>
     <% if node['nginx']['cache']['proxy']['enable'] -%>
-    proxy_cache_path /var/cache/nginx/proxy-cache levels=1:2 keys_zone=<%= node['nginx']['cache']['proxy']['keys_zone'] %> inactive=<%= node['nginx']['cache']['proxy']['inactive'] %> max_size=<%= node['nginx']['cache']['proxy']['max_size'] %>;
+    proxy_cache_path <%= node['nginx']['cache']['proxy']['directory'] %> levels=2:2:2 use_temp_path=off keys_zone=<%= node['nginx']['cache']['proxy']['keys_zone'] %> inactive=<%= node['nginx']['cache']['proxy']['inactive'] %> max_size=<%= node['nginx']['cache']['proxy']['max_size'] %>;
     <% end -%>
 
+    # Internal site for munin monitoring
+    server {
+      listen 127.0.0.1:8050;
+      server_name localhost;
+      location /nginx_status {
+        stub_status on;
+        access_log off;
+        allow 127.0.0.1;
+        deny all;
+      }
+    }
+
     include /etc/nginx/conf.d/*.conf;
 }
index 9d30c164fcb032f6ba00b1861496ff86d5d81d5f..b5024147acc891f509a64d3805adda1e9454641a 100644 (file)
@@ -21,7 +21,7 @@ require "json"
 
 default_action :install
 
-property :package, :kind_of => String, :name_attribute => true
+property :package, :kind_of => String, :name_property => true
 property :version, :kind_of => String
 
 action :install do
index 67708f9a1423691af2605039184c44f67dcaca77..55a2d836dcb8637d13a4212f38d9680b37970c57 100644 (file)
@@ -1,29 +1,27 @@
 default[:nominatim][:state] = "off" # or: standalone, master, slave
 default[:nominatim][:dbadmins] = []
+default[:nominatim][:dbcluster] = "12/main"
 default[:nominatim][:dbname] = "nominatim"
 default[:nominatim][:tablespaces] = []
+default[:nominatim][:postgis] = "2.5"
 default[:nominatim][:logdir] = "/var/log/nominatim"
 default[:nominatim][:repository] = "https://git.openstreetmap.org/public/nominatim.git"
 default[:nominatim][:revision] = "master"
 default[:nominatim][:enable_backup] = false
 default[:nominatim][:enable_git_updates] = true
+default[:nominatim][:ui_repository] = "https://git.openstreetmap.org/public/nominatim-ui.git"
+default[:nominatim][:ui_revision] = "master"
 
 default[:nominatim][:fpm_pools] = {
-  :www => {
-    :port => "8000",
+  "nominatim.openstreetmap.org" => {
     :pm => "dynamic",
-    :max_children => "60"
-  },
-  :bulk => {
-    :port => "8001",
-    :pm => "static",
-    :max_children => "10"
-  },
-  :details => {
-    :port => "8002",
-    :pm => "static",
-    :max_children => "2"
+    :max_children => 60,
+    :prometheus_port => 9253
   }
 }
 
 default[:nominatim][:redirects] = {}
+
+default[:postgresql][:versions] |= [node[:nominatim][:dbcluster].split("/").first]
+
+default[:accounts][:users][:nominatim][:status] = :role
index 5909c6caf2c19703f917d2d7b61df9c93d6e2186..de51c87ca7feb78700a9cb5be27b2ab88dee772c 100644 (file)
@@ -6,8 +6,12 @@ description       "Installs and configures nominatim servers"
 
 version           "1.0.0"
 supports          "ubuntu"
-depends           "apache"
-depends           "postgresql"
-depends           "git"
+depends           "accounts"
 depends           "fail2ban"
+depends           "git"
+depends           "munin"
+depends           "nginx"
+depends           "php"
+depends           "postgresql"
 depends           "python"
+depends           "systemd"
index 47b52274fd63be22fd455916c818b1054df02d6e..3b4fc7df108237b12945c2fff7925572a96273da 100644 (file)
 # limitations under the License.
 #
 
+include_recipe "accounts"
+include_recipe "munin"
+include_recipe "php::fpm"
+
 basedir = data_bag_item("accounts", "nominatim")["home"]
 email_errors = data_bag_item("accounts", "lonvia")["email"]
 
 directory basedir do
   owner "nominatim"
   group "nominatim"
-  mode 0o755
+  mode "755"
   recursive true
 end
 
 directory node[:nominatim][:logdir] do
   owner "nominatim"
   group "nominatim"
-  mode 0o755
+  mode "755"
   recursive true
 end
 
@@ -38,14 +42,25 @@ file "#{node[:nominatim][:logdir]}/query.log" do
   action :create_if_missing
   owner "www-data"
   group "adm"
-  mode 0o664
+  mode "664"
 end
 
 file "#{node[:nominatim][:logdir]}/update.log" do
   action :create_if_missing
   owner "nominatim"
   group "adm"
-  mode 0o664
+  mode "664"
+end
+
+# exception granted for a limited time so that they can set up their own server
+firewall_rule "increase-limits-gnome-proxy" do
+  action :accept
+  family "inet"
+  source "net:8.43.85.23"
+  dest "fw"
+  proto "tcp:syn"
+  dest_ports "https"
+  rate_limit "s:10/sec:30"
 end
 
 ## Postgresql
@@ -55,7 +70,6 @@ include_recipe "postgresql"
 postgresql_version = node[:nominatim][:dbcluster].split("/").first
 postgis_version = node[:nominatim][:postgis]
 
-package "postgis"
 package "postgresql-#{postgresql_version}-postgis-#{postgis_version}"
 
 node[:nominatim][:dbadmins].each do |user|
@@ -85,17 +99,17 @@ end
 directory "#{basedir}/tablespaces" do
   owner "postgres"
   group "postgres"
-  mode 0o700
+  mode "700"
 end
 
-# Note: tablespaces must be exactly in the same location on each
+# NOTE: tablespaces must be exactly in the same location on each
 #       Nominatim instance when replication is in use. Therefore
 #       use symlinks to canonical directory locations.
 node[:nominatim][:tablespaces].each do |name, location|
   directory location do
     owner "postgres"
     group "postgres"
-    mode 0o700
+    mode "700"
     recursive true
   end
 
@@ -119,14 +133,14 @@ if node[:nominatim][:state] == "master"
   directory node[:rsyncd][:modules][:archive][:path] do
     owner "postgres"
     group "postgres"
-    mode 0o700
+    mode "700"
   end
 
   template "/usr/local/bin/clean-db-nominatim" do
     source "clean-db-nominatim.erb"
     owner "root"
     group "root"
-    mode 0o755
+    mode "755"
     variables :archive_dir => node[:rsyncd][:modules][:archive][:path],
               :update_stop_file => "#{basedir}/status/updates_disabled",
               :streaming_clients => search(:node, "nominatim_state:slave").map { |slave| slave[:fqdn] }.join(" ")
@@ -153,15 +167,23 @@ package %w[
   libproj-dev
   python3-pyosmium
   pyosmium
+  python3-psycopg2
+  python3-dotenv
+  python3-psutil
+  python3-jinja2
+  php-pgsql
+  php-intl
+  php-symfony-dotenv
 ]
 
 source_directory = "#{basedir}/nominatim"
 build_directory = "#{basedir}/bin"
+ui_directory = "#{basedir}/ui"
 
 directory build_directory do
   owner "nominatim"
   group "nominatim"
-  mode 0o755
+  mode "755"
   recursive true
 end
 
@@ -178,7 +200,15 @@ git source_directory do
   user "nominatim"
   group "nominatim"
   not_if { node[:nominatim][:state] != "slave" && File.exist?("#{source_directory}/README.md") }
-  notifies :run, "execute[compile_nominatim]", :immediately
+  notifies :run, "execute[compile_nominatim]"
+end
+
+remote_file "#{source_directory}/data/country_osm_grid.sql.gz" do
+  action :create_if_missing
+  source "https://www.nominatim.org/data/country_grid.sql.gz"
+  owner "nominatim"
+  group "nominatim"
+  mode "644"
 end
 
 execute "compile_nominatim" do
@@ -192,23 +222,38 @@ template "#{source_directory}/.git/hooks/post-merge" do
   source "git-post-merge-hook.erb"
   owner "nominatim"
   group "nominatim"
-  mode 0o755
+  mode "755"
   variables :srcdir => source_directory,
             :builddir => build_directory,
             :dbname => node[:nominatim][:dbname]
 end
 
-template "#{build_directory}/settings/local.php" do
-  source "settings.erb"
+template "#{build_directory}/.env" do
+  source "nominatim.env.erb"
   owner "nominatim"
   group "nominatim"
-  mode 0o664
+  mode "664"
   variables :base_url => node[:nominatim][:state] == "off" ? node[:fqdn] : "nominatim.openstreetmap.org",
             :dbname => node[:nominatim][:dbname],
             :flatnode_file => node[:nominatim][:flatnode_file],
             :log_file => "#{node[:nominatim][:logdir]}/query.log"
 end
 
+git ui_directory do
+  action :sync
+  repository node[:nominatim][:ui_repository]
+  revision node[:nominatim][:ui_revision]
+  user "nominatim"
+  group "nominatim"
+end
+
+template "#{ui_directory}/dist/theme/config.theme.js" do
+  source "ui-config.js.erb"
+  owner "nominatim"
+  group "nominatim"
+  mode "664"
+end
+
 if node[:nominatim][:flatnode_file]
   directory File.dirname(node[:nominatim][:flatnode_file]) do
     recursive true
@@ -219,49 +264,83 @@ template "/etc/logrotate.d/nominatim" do
   source "logrotate.nominatim.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 external_data = [
-  "wikipedia_article.sql.bin",
-  "wikipedia_redirect.sql.bin",
-  "gb_postcode_data.sql.gz"
+  "wikimedia-importance.sql.gz",
+  "gb_postcode_data.sql.gz",
+  "us_postcode_data.sql.gz"
 ]
 
 external_data.each do |fname|
-  remote_file "#{source_directory}/data/#{fname}" do
+  remote_file "#{build_directory}/#{fname}" do
     action :create_if_missing
     source "https://www.nominatim.org/data/#{fname}"
     owner "nominatim"
     group "nominatim"
-    mode 0o644
+    mode "644"
   end
 end
 
-remote_file "#{source_directory}/data/country_osm_grid.sql.gz" do
-  action :create_if_missing
-  source "https://www.nominatim.org/data/country_grid.sql.gz"
-  owner "nominatim"
-  group "nominatim"
-  mode 0o644
-end
+if node[:nominatim][:state] == "off"
+  cron_d "nominatim-backup" do
+    action :delete
+  end
 
-template "/etc/cron.d/nominatim" do
-  action node[:nominatim][:state] == "off" ? :delete : :create
-  source "nominatim.cron.erb"
-  owner "root"
-  group "root"
-  mode "0644"
-  variables :bin_directory => "#{source_directory}/utils",
-            :mailto => email_errors,
-            :update_maintenance_trigger => "#{basedir}/status/update_maintenance"
+  cron_d "nominatim-vacuum-db" do
+    action :delete
+  end
+
+  cron_d "nominatim-clean-db" do
+    action :delete
+  end
+
+  cron_d "nominatim-update-maintenance-trigger" do
+    action :delete
+  end
+else
+  cron_d "nominatim-backup" do
+    action node[:nominatim][:enable_backup] ? :create : :delete
+    minute "0"
+    hour "3"
+    day "1"
+    user "nominatim"
+    command "/usr/local/bin/backup-nominatim"
+    mailto email_errors
+  end
+
+  cron_d "nominatim-vacuum-db" do
+    minute "20"
+    hour "0"
+    user "postgres"
+    command "/usr/local/bin/vacuum-db-nominatim"
+    mailto email_errors
+  end
+
+  cron_d "nominatim-clean-db" do
+    action node[:nominatim][:state] == "master" ? :create : :delete
+    minute "5"
+    hour "*/4"
+    user "postgres"
+    command "/usr/local/bin/clean-db-nominatim"
+    mailto email_errors
+  end
+
+  cron_d "nominatim-update-maintenance-trigger" do
+    minute "18"
+    hour "1"
+    user "nominatim"
+    command "touch #{basedir}/status/update_maintenance"
+    mailto email_errors
+  end
 end
 
 template "#{source_directory}/utils/nominatim-update" do
   source "updater.erb"
   user "nominatim"
   group "nominatim"
-  mode 0o755
+  mode "755"
   variables :bindir => build_directory,
             :srcdir => source_directory,
             :logfile => "#{node[:nominatim][:logdir]}/update.log",
@@ -274,7 +353,7 @@ template "/etc/init.d/nominatim-update" do
   source "updater.init.erb"
   user "nominatim"
   group "nominatim"
-  mode 0o755
+  mode "755"
   variables :source_directory => source_directory
 end
 
@@ -283,94 +362,81 @@ end
     source "#{fname}.erb"
     owner "root"
     group "root"
-    mode 0o755
+    mode "755"
     variables :db => node[:nominatim][:dbname]
   end
 end
 
 ## webserver frontend
 
-template "#{build_directory}/settings/ip_blocks.conf" do
-  action :create_if_missing
-  source "ipblocks.erb"
-  owner "nominatim"
-  group "nominatim"
-  mode 0o664
-end
-
-file "#{build_directory}/settings/apache_blocks.conf" do
-  action :create_if_missing
+directory "#{basedir}/etc" do
   owner "nominatim"
-  group "nominatim"
-  mode 0o664
-end
-
-file "#{build_directory}/settings/ip_blocks.map" do
-  action :create_if_missing
-  owner "nominatim"
-  group "nominatim"
-  mode 0o664
+  group "adm"
+  mode "775"
 end
 
-include_recipe "apache"
-
-package "php"
-package "php-fpm"
-package "php-pgsql"
-package "php-intl"
-
-apache_module "rewrite"
-apache_module "proxy"
-apache_module "proxy_fcgi"
-apache_module "proxy_http"
-apache_module "headers"
-
-service "php7.2-fpm" do
-  action [:enable, :start]
-  supports :status => true, :restart => true, :reload => true
+%w[user_agent referrer email generic].each do |name|
+  file "#{basedir}/etc/nginx_blocked_#{name}.conf" do
+    action :create_if_missing
+    owner "nominatim"
+    group "adm"
+    mode "664"
+  end
 end
 
 node[:nominatim][:fpm_pools].each do |name, data|
-  template "/etc/php/7.2/fpm/pool.d/#{name}.conf" do
-    source "fpm.conf.erb"
-    owner "root"
-    group "root"
-    mode 0o644
-    variables data.merge(:name => name)
-    notifies :reload, "service[php7.2-fpm]"
+  php_fpm name do
+    port data[:port]
+    pm data[:pm]
+    pm_max_children data[:max_children]
+    pm_start_servers 20
+    pm_min_spare_servers 10
+    pm_max_spare_servers 20
+    pm_max_requests 10000
+    prometheus_port data[:prometheus_port]
   end
 end
 
-ssl_certificate "nominatim.openstreetmap.org" do
-  domains ["nominatim.openstreetmap.org",
+ssl_certificate node[:fqdn] do
+  domains [node[:fqdn],
+           "nominatim.openstreetmap.org",
            "nominatim.osm.org",
            "nominatim.openstreetmap.com",
            "nominatim.openstreetmap.net",
            "nominatim.openstreetmaps.org",
-           "nominatim.openmaps.org"]
-  notifies :reload, "service[apache2]"
+           "nominatim.openmaps.org",
+           "nominatim.qgis.org"]
+  notifies :reload, "service[nginx]"
 end
 
-apache_site "nominatim.openstreetmap.org" do
-  template "apache.erb"
-  directory build_directory
-  variables :pools => node[:nominatim][:fpm_pools]
-  only_if { node[:nominatim][:state] != "off" }
+package "apache2" do
+  action :remove
 end
 
-apache_site "default" do
-  action [:disable]
+include_recipe "nginx"
+
+nginx_site "default" do
+  action [:delete]
+end
+
+frontends = search(:node, "recipes:web\\:\\:frontend").sort_by(&:name)
+
+nginx_site "nominatim" do
+  template "nginx.erb"
+  directory build_directory
+  variables :pools => node[:nominatim][:fpm_pools],
+            :frontends => frontends,
+            :confdir => "#{basedir}/etc",
+            :ui_directory => ui_directory
 end
 
-template "/etc/logrotate.d/apache2" do
-  source "logrotate.apache.erb"
+template "/etc/logrotate.d/nginx" do
+  source "logrotate.nginx.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
-include_recipe "fail2ban"
-
 munin_plugin_conf "nominatim" do
   template "munin.erb"
   variables :db => node[:nominatim][:dbname],
@@ -389,12 +455,20 @@ munin_plugin "nominatim_requests" do
   target "#{source_directory}/munin/nominatim_requests_querylog"
 end
 
-munin_plugin "nominatim_throttled_ips" do
-  target "#{source_directory}/munin/nominatim_throttled_ips"
-end
-
 directory "#{basedir}/status" do
   owner "nominatim"
   group "postgres"
-  mode 0o775
+  mode "775"
+end
+
+include_recipe "fail2ban"
+
+frontend_addresses = frontends.collect { |f| f.ipaddresses(:role => :external) }
+
+fail2ban_jail "nominatim_limit_req" do
+  filter "nginx-limit-req"
+  logpath "#{node[:nominatim][:logdir]}/nominatim.openstreetmap.org-error.log"
+  ports [80, 443]
+  maxretry 20
+  ignoreips frontend_addresses.flatten.sort
 end
diff --git a/cookbooks/nominatim/templates/default/apache.erb b/cookbooks/nominatim/templates/default/apache.erb
deleted file mode 100644 (file)
index 9d29290..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-
-<VirtualHost *:443>
-    ServerName <%= node[:fqdn] %>
-    ServerAlias nominatim.openstreetmap.org
-    ServerAlias nominatim.osm.org
-    ServerAlias nominatim.openstreetmap.com
-    ServerAlias nominatim.openstreetmap.net
-    ServerAlias nominatim.openstreetmaps.org
-    ServerAlias nominatim.openmaps.org
-    ServerAdmin webmaster@openstreetmap.org
-
-    # Enable SSL
-    SSLEngine on
-    SSLProxyEngine on
-    SSLCertificateFile /etc/ssl/certs/nominatim.openstreetmap.org.pem
-    SSLCertificateKeyFile /etc/ssl/private/nominatim.openstreetmap.org.key
-
-    # Remove Proxy request header to mitigate https://httpoxy.org/
-    RequestHeader unset Proxy early
-
-    RequestReadTimeout header=15-30,MinRate=500 body=15-30,MinRate=500
-
-    CustomLog <%= node[:nominatim][:logdir] %>/nominatim.openstreetmap.org-access.log combined
-    ErrorLog /var/log/apache2/nominatim.openstreetmap.org-error.log
-
-    DocumentRoot <%= @directory %>/website
-    <Directory "<%= @directory %>/website/">
-        DirectoryIndex search.php
-        Options FollowSymLinks
-        Require all granted
-    </Directory>
-
-    ProxyPassMatch ^/([^/]*\.php(/.*)?)$ fcgi://127.0.0.1:<%= @pools[:www][:port ]%><%= @directory %>/website/$1
-
-    <% @pools.each do |name,details| -%>
-    Alias /pool-<%= name %>/ "<%= @directory %>/website/"
-    <% node[:nominatim][:redirects].each do |url,host| -%>
-    ProxyPassMatch ^/pool-<%= name %>/(<%= url %>\.php(/.*)?) http<% if port == 443 -%>s<% end -%>://<%= host %>/pool-<%= name %>/$1
-    <% end -%>
-    ProxyPassMatch ^/pool-<%= name %>/(.*\.php(/.*)?) fcgi://127.0.0.1:<%= details[:port ]%><%= @directory %>/website/$1
-    <% end -%>
-
-    Redirect 429 /pool-block/
-    ErrorDocument 429 /509.html
-    <Location /pool-block>
-        ErrorDocument 429 /509.html
-    </Location>
-    Redirect 403 /pool-ban/
-    <Location /pool-ban>
-        ErrorDocument 403 /403.html
-    </Location>
-    ErrorDocument 403 /403.html
-
-    RewriteEngine On
-
-    # manual blocks
-    Include <%= @directory %>/settings/apache_blocks.conf
-
-    # regular requests and autoblocks
-    RewriteMap bulklist txt:<%= @directory %>/settings/ip_blocks.map
-    RewriteRule ^/(search|reverse|lookup)(\.php)?(/.*)? /pool-${bulklist:%{REMOTE_ADDR}|www}/$1.php$3 [PT]
-    RewriteRule ^/details(\.php)?(/.*)? /pool-${bulklist:%{REMOTE_ADDR}|details}/details.php$2 [PT]
-</VirtualHost>
-
-<VirtualHost *:80>
-    ServerName <%= node[:fqdn] %>
-    ServerAlias nominatim.openstreetmap.org
-    ServerAlias nominatim.osm.org
-    ServerAlias nominatim.openstreetmap.com
-    ServerAlias nominatim.openstreetmap.net
-    ServerAlias nominatim.openstreetmaps.org
-    ServerAlias nominatim.openmaps.org
-    ServerAdmin webmaster@openstreetmap.org
-
-    CustomLog <%= node[:nominatim][:logdir] %>/nominatim.openstreetmap.org-access.log combined
-    ErrorLog /var/log/apache2/nominatim.openstreetmap.org-error.log
-
-    RewriteEngine On
-
-    # manual blocks
-    Include <%= @directory %>/settings/apache_blocks.conf
-
-    RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
-    RedirectPermanent / https://nominatim.openstreetmap.org/
-</VirtualHost>
diff --git a/cookbooks/nominatim/templates/default/fpm.conf.erb b/cookbooks/nominatim/templates/default/fpm.conf.erb
deleted file mode 100644 (file)
index 386769e..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-; DO NOT EDIT - This file is being maintained by Chef
-
-[<%= @name %>]
-<% if @port -%>
-listen = 127.0.0.1:<%= @port %>
-<% else -%>
-listen = /var/run/php5-fpm-<%= @name %>.sock
-listen.owner = www-data
-listen.group = www-data
-<% end -%>
-
-user = www-data
-group = www-data
-
-pm = <%= @pm %>
-pm.max_children = <%= @max_children %>
-pm.start_servers = 20
-pm.min_spare_servers = 10
-pm.max_spare_servers = 20
-pm.max_requests = 10000
-
-security.limit_extensions = .php .phpx .phpj
index a1ee3179508274024ec22b1195bfb8da030c55f4..fc806f1b484408701ddfc89a0d36dd12bb97aea4 100644 (file)
@@ -13,6 +13,5 @@ make
 
 psql -d <%= @dbname %> -c "SELECT version();" >/dev/null 2>&1
 if [[ "$?" == "0" ]]; then
-  ./utils/setup.php --create-functions --create-partition-functions --enable-diff-updates
-  ./utils/update.php --update-address-levels
+  ./nominatim refresh --functions --address-levels --website
 fi
similarity index 50%
rename from cookbooks/nominatim/templates/default/logrotate.apache.erb
rename to cookbooks/nominatim/templates/default/logrotate.nginx.erb
index 8835397f3081a2a0e2611d3f9c1d67acf31ccb8d..3dffbd216d1e44e46bc226f0fdf71189ef3e77b9 100644 (file)
@@ -1,30 +1,29 @@
 # DO NOT EDIT - This file is being maintained by Chef
 
-/var/log/apache2/*.log {
+/var/log/nginx/*.log {
   daily
   missingok
-  rotate 42
+  rotate 7
   compress
   delaycompress
   notifempty
-  create 640 root adm
+  create 640 nginx adm
   sharedscripts
   postrotate
-    /bin/systemctl reload apache2
+    [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
   endscript
 }
 
-
-<%= node[:nominatim][:logdir] %>/nominatim.openstreetmap.org-access.log {
+<%= node[:nominatim][:logdir] %>/nominatim.openstreetmap.org-*.log {
   daily
   missingok
-  rotate 42
+  rotate 28
   compress
   delaycompress
   notifempty
   create 640 root adm
   sharedscripts
   postrotate
-    /bin/systemctl reload apache2
+    [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
   endscript
 }
index b5e9d2ac3f7ff9950a0f3f5b477c890a2d77eea1..ba7a5bc3f590a2b99b84efc52f776c2383998ccc 100644 (file)
@@ -3,7 +3,7 @@
 <%= node[:nominatim][:logdir] %>/update.log {
   weekly
   missingok
-  rotate 5
+  rotate 30
   compress
   delaycompress
   notifempty
   notifempty
   create 640 www-data adm
 }
-
-<%= node[:nominatim][:logdir] %>/restricted_ips.log {
-  weekly
-  missingok
-  rotate 5
-  compress
-  delaycompress
-  notifempty
-  create 660 nominatim adm
-}
diff --git a/cookbooks/nominatim/templates/default/nginx.erb b/cookbooks/nominatim/templates/default/nginx.erb
new file mode 100644 (file)
index 0000000..0f9765f
--- /dev/null
@@ -0,0 +1,216 @@
+upstream nominatim_service {
+  server unix:/run/php/nominatim.openstreetmap.org.sock;
+}
+
+map $uri $nominatim_script_name {
+    ~^(.+?\.php)         $1;
+    ~^/([^/]+)           $1.php;
+    ^$                   search.php;
+}
+
+map $uri $nominatim_path_info {
+    ~^/([^/]+)(.*)$      $2;
+}
+
+map $args $format {
+    default                  default;
+    ~(^|&)format=html(&|$)   html;
+    ~(^|&)format=            other;
+}
+
+map $uri/$format $forward_to_ui {
+    default               1;
+    ~^/ui                 0;
+    ~/other$              0;
+    ~/reverse.*/default   0;
+    ~/lookup.*/default    0;
+    ~/status.*/default    0;
+}
+
+map $query_string $email_id {
+    ~(^|&)email=([^&]+)  $2;
+}
+
+map $email_id $missing_email {
+    default "";
+    "" 1;
+}
+
+map $http_user_agent $missing_ua {
+    default "";
+    "" 1;
+}
+
+map $http_referer $missing_referer {
+    default "";
+    "" 1;
+}
+
+# Whitelisted IPs
+geo $whitelisted {
+    default 0;
+<% @frontends.each do |frontend| -%>
+<% frontend.ipaddresses(:role => :external).sort.each do |address| -%>
+    <%= address %> 1;
+<% end -%>
+<% end -%>
+    46.235.224.148 1;
+    209.132.180.180 1;
+    209.132.180.168 1;
+    8.43.85.23 1; # gnome
+}
+
+map $missing_email$missing_referer$http_user_agent $blocked_user_agent {
+   default 0;
+   "11" 2; # block any requests without identifier
+   include <%= @confdir %>/nginx_blocked_user_agent.conf;
+}
+
+map $missing_email$missing_ua$http_referer $blocked_referrer {
+   default 0;
+   include <%= @confdir %>/nginx_blocked_referrer.conf;
+}
+
+map $missing_referer$missing_ua$email_id $blocked_email {
+   default 0;
+   include <%= @confdir %>/nginx_blocked_email.conf;
+}
+
+map $whitelisted $limit_www {
+    1 "";
+    0 $binary_remote_addr;
+}
+
+map $blocked_user_agent $limit_tarpit {
+    0 "";
+    1 $binary_remote_addr;
+    2 $binary_remote_addr;
+}
+
+map $missing_email$missing_referer$http_user_agent $generic_mozilla {
+    default 0;
+    ~^11Mozilla/4.0 1;
+    ~^11Mozilla/5.0 2;
+}
+
+map $whitelisted$generic_mozilla$uri $limit_reverse {
+    default "";
+    ~01/reverse.*  $binary_remote_addr;
+    ~02/reverse.*  $binary_remote_addr;
+}
+
+limit_req_zone $limit_www zone=www:50m rate=2r/s;
+limit_req_zone $limit_tarpit zone=tarpit:10m rate=1r/s;
+limit_req_zone $binary_remote_addr zone=blocked:10m rate=20r/m;
+limit_req_zone $limit_reverse zone=reverse:10m rate=10r/m;
+
+server {
+    listen 80 default_server;
+    listen [::]:80 default_server;
+
+    access_log <%= node[:nominatim][:logdir] %>/nominatim.openstreetmap.org-access.log combined;
+    error_log <%= node[:nominatim][:logdir] %>/nominatim.openstreetmap.org-error.log;
+
+    location /nginx_status {
+        stub_status on;
+        access_log   off;
+        allow 127.0.0.1;
+        allow ::1;
+        deny all;
+    }
+
+     rewrite ^/\.well-known/acme-challenge/(.*)$ http://acme.openstreetmap.org/.well-known/acme-challenge/$1 permanent;
+
+     location / {
+         return 301 https://$host$request_uri;
+     }
+}
+
+server {
+    # IPv4
+    listen       443 ssl deferred backlog=16384 reuseport http2 default_server;
+    # IPv6
+    listen       [::]:443 ssl deferred backlog=16384 reuseport http2 default_server;
+    server_name  localhost;
+
+    ssl_certificate /etc/ssl/certs/<%= node[:fqdn] %>.pem;
+    ssl_certificate_key /etc/ssl/private/<%= node[:fqdn] %>.key;
+
+    root <%= @directory %>/website;
+    index search.php;
+
+    access_log <%= node[:nominatim][:logdir] %>/nominatim.openstreetmap.org-access.log combined;
+    error_log <%= node[:nominatim][:logdir] %>/nominatim.openstreetmap.org-error.log;
+
+    location /nginx_status {
+        stub_status on;
+        access_log   off;
+        allow 127.0.0.1;
+        allow ::1;
+        deny all;
+    }
+
+    error_page 403 /403.html;
+    location /403.html {
+        limit_req zone=blocked burst=5;
+    }
+
+    error_page 429 /509.html;
+    location /509.html {
+        limit_req zone=blocked burst=5;
+    }
+
+    location / {
+        try_files $uri $uri/ @php;
+    }
+
+    location /ui/ {
+        alias <%= @ui_directory %>/dist/;
+        index search.html;
+    }
+
+    location @php {
+        if ($blocked_user_agent ~ ^2$)
+        { return 403; }
+        if ($blocked_referrer)
+        { return 403; }
+        if ($blocked_email)
+        { return 403; }
+        include <%= @confdir %>/nginx_blocked_generic.conf;
+
+        limit_req zone=www burst=10;
+        limit_req zone=tarpit burst=5;
+        limit_req zone=reverse burst=5;
+        limit_req_status 429;
+        fastcgi_pass nominatim_service;
+        include fastcgi_params;
+        fastcgi_param QUERY_STRING    $args;
+        fastcgi_param PATH_INFO       "$nominatim_path_info";
+        fastcgi_param SCRIPT_FILENAME  "$document_root/$nominatim_script_name";
+        if ($forward_to_ui) {
+            rewrite ^(/[^/]*) https://$host/ui$1.html redirect;
+        }
+    }
+
+    location ~* \.php$ {
+        if ($blocked_user_agent ~ ^2$)
+        { return 403; }
+        if ($blocked_referrer)
+        { return 403; }
+        if ($blocked_email)
+        { return 403; }
+        include <%= @confdir %>/nginx_blocked_generic.conf;
+
+        limit_req zone=www burst=10;
+        limit_req zone=tarpit burst=2;
+        limit_req zone=reverse burst=5;
+        limit_req_status 429;
+        fastcgi_pass    nominatim_service;
+        include         fastcgi_params;
+        fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
+
+        if ($forward_to_ui) {
+            rewrite (.*).php https://$host/ui$1.html redirect;
+        }
+    }
+}
diff --git a/cookbooks/nominatim/templates/default/nominatim.cron.erb b/cookbooks/nominatim/templates/default/nominatim.cron.erb
deleted file mode 100644 (file)
index 5ae8f3a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# Maintained by chef. DO NOT EDIT.
-
-MAILTO=<%= @mailto %>
-
-* * * * * lonvia <%= @bin_directory %>/cron_ipanalyse.py <%= node[:nominatim][:logdir] %>/nominatim.openstreetmap.org-access.log
-<% if node[:nominatim][:enable_backup] -%>
-00 3 1 * * nominatim /usr/local/bin/backup-nominatim
-<% end -%>
-20 0 * * * postgres /usr/local/bin/vacuum-db-nominatim
-<% if node[:nominatim][:state] == "master" -%>
-05 */4 * * * postgres /usr/local/bin/clean-db-nominatim
-<% end -%>
-18 1 * * * nominatim touch <%= @update_maintenance_trigger %>
diff --git a/cookbooks/nominatim/templates/default/nominatim.env.erb b/cookbooks/nominatim/templates/default/nominatim.env.erb
new file mode 100644 (file)
index 0000000..f26a7ba
--- /dev/null
@@ -0,0 +1,28 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+NOMINATIM_DATABASE_DSN="pgsql:dbname=<%= @dbname %>"
+NOMINATIM_MAPICON_URL="https://<%= @base_url %>/ui/mapicons/"
+
+<% if @flatnode_file -%>
+NOMINATIM_FLATNODE_FILE="<%= @flatnode_file %>"
+<% end -%>
+
+NOMINATIM_IMPORT_STYLE=extratags
+
+NOMINATIM_USE_US_TIGER_DATA=yes
+
+NOMINATIM_PYOSMIUM_BINARY=/usr/bin/pyosmium-get-changes
+
+NOMINATIM_TABLESPACE_SEARCH_DATA=dsearch
+NOMINATIM_TABLESPACE_SEARCH_INDEX=isearch
+NOMINATIM_TABLESPACE_OSM_DATA=dosm
+NOMINATIM_TABLESPACE_OSM_INDEX=iosm
+NOMINATIM_TABLESPACE_PLACE_DATA=dplace
+NOMINATIM_TABLESPACE_PLACE_INDEX=iplace
+NOMINATIM_TABLESPACE_ADDRESS_DATA=daddress
+NOMINATIM_TABLESPACE_ADDRESS_INDEX=iaddress
+NOMINATIM_TABLESPACE_AUX_DATA=daux
+NOMINATIM_TABLESPACE_AUX_INDEX=iaux
+
+NOMINATIM_LOG_DB=no
+NOMINATIM_LOG_FILE="<%= @log_file %>"
diff --git a/cookbooks/nominatim/templates/default/settings.erb b/cookbooks/nominatim/templates/default/settings.erb
deleted file mode 100644 (file)
index 18858ca..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-# DO NOT EDIT - This file is being maintained by Chef
-
-@define('CONST_Database_DSN', 'pgsql:dbname=<%= @dbname %>');
-@define('CONST_Website_BaseURL', 'https://<%= @base_url %>/');
-
-<% if @flatnode_file -%>
-@define('CONST_Osm2pgsql_Flatnode_File', '<%= @flatnode_file %>');
-<% end -%>
-@define('CONST_Search_NameOnlySearchFrequencyThreshold', 500);
-
-@define('CONST_Use_US_Tiger_Data', true);
-
-@define('CONST_Tablespace_Osm2pgsql_Data', 'dosm');
-@define('CONST_Tablespace_Osm2pgsql_Index', 'iosm');
-@define('CONST_Tablespace_Place_Data', 'dplace');
-@define('CONST_Tablespace_Place_Index', 'iplace');
-@define('CONST_Tablespace_Address_Data', 'daddress');
-@define('CONST_Tablespace_Address_Index', 'iaddress');
-@define('CONST_Tablespace_Search_Data', 'dsearch');
-@define('CONST_Tablespace_Search_Index', 'isearch');
-@define('CONST_Tablespace_Aux_Data', 'daux');
-@define('CONST_Tablespace_Aux_Index', 'iaux');
-
-@define('CONST_Log_File', '<%= @log_file %>');
-@define('CONST_Log_DB', false);
diff --git a/cookbooks/nominatim/templates/default/ui-config.js.erb b/cookbooks/nominatim/templates/default/ui-config.js.erb
new file mode 100644 (file)
index 0000000..14ae831
--- /dev/null
@@ -0,0 +1,6 @@
+// DO NOT EDIT - This file is being maintained by Chef
+
+Nominatim_Config['Nominatim_API_Endpoint'] = '/';
+Nominatim_Config['Images_Base_Url'] = '/ui/mapicons/';
+
+Nominatim_Config['Page_Title'] = 'Nominatim';
index ade5845aa6fda850f5d16801cef83c1afb012d3e..37cf8937291828771e9012f789a84cd791ee04da 100644 (file)
@@ -17,12 +17,12 @@ do
 
     if [[ $current_load -lt $num_cpus ]]
     then
-        INST=2
+        INST=4
     else
-        INST=1
+        INST=2
     fi
 
-    ./utils/update.php --import-osmosis --index-instances $INST
+    ./nominatim replication --once --threads $INST
 
 <% if node[:nominatim][:enable_git_updates] -%>
     pushd <%= @srcdir %>
@@ -37,6 +37,6 @@ do
 
     if [ -f "<%= @update_maintenance_trigger %>" ]; then
         rm <%= @update_maintenance_trigger %>
-        ./utils/update.php --calculate-postcodes
+        ./nominatim refresh --postcodes
     fi
 done
index 910386b24b710d30afad603fd364b869a0449f4d..f80c8dbeefa0e0b0e1d840f21d666636fd9c2fb7 100644 (file)
@@ -6,3 +6,5 @@ description       "Installs and configures ntp as a client or server"
 
 version           "0.8.2"
 supports          "ubuntu"
+depends           "munin"
+depends           "systemd"
index 66acd1991e3c6308d1d71695cc540dac2823b4e1..02c80bc011f080db4d04c79253a86dbd9d2d1450 100644 (file)
@@ -17,6 +17,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+include_recipe "munin"
+
 package %w[
   chrony
   tzdata
@@ -40,7 +42,7 @@ template "/etc/chrony/chrony.conf" do
   source "chrony.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[chrony]"
 end
 
@@ -48,8 +50,24 @@ service "systemd-timesyncd" do
   action [:stop, :disable]
 end
 
+systemd_service "chrony-restart" do
+  service "chrony"
+  dropin "restart"
+  restart "on-failure"
+  notifies :restart, "service[chrony]"
+end
+
 service "chrony" do
   action [:enable, :start]
 end
 
 munin_plugin "chrony"
+
+# chrony occasionally marks all servers offline during a network outage.
+# force online all sources during a chef run
+execute "chronyc-online" do
+  command "/usr/bin/chronyc online"
+  user "root"
+  group "root"
+  ignore_failure true
+end
index 7f54a898f4539fe381ebda20f272aacea185d775..03728fddb8c60d3b754555c81240ea87c38b5768 100644 (file)
@@ -4,6 +4,17 @@
 <% node[:ntp][:servers].each do |server| -%>
 pool <%= server %> iburst
 <% end -%>
+# Add additional non-pool NTP servers
+# pool.ntp.org can sometimes be aggressive with KoD
+pool time.cloudflare.com iburst
+pool time.google.com iburst
+
+# Allow local queries for monitoring
+allow 127.0.0.1/32
+allow ::1/128
+
+# Run an initial NTP sync on daemon startup
+initstepslew 30 time.cloudflare.com time.google.com <%= node[:ntp][:servers].join(" ") %>
 
 # This directive specify the location of the file containing ID/key pairs for
 # NTP authentication.
@@ -26,10 +37,18 @@ maxupdateskew 100.0
 # real-time clock. Note that it can’t be used along with the 'rtcfile' directive.
 rtcsync
 
+<% if node[:virtualization][:role] == "guest" -%>
+# Allow anytime step on VM guests
+makestep 1 -1
+<% else -%>
 # Step the system clock instead of slewing it if the adjustment is larger than
 # one second, but only in the first three clock updates.
 makestep 1 3
+<% end -%>
 
 # Enable leap second slew
 leapsecmode slew
 maxslewrate 1000
+
+# Enable hardware timestamps if available
+hwtimestamp *
index 54e40108270c24c9a8b0808f6d0f54e4176bdd9c..5d550371faf7997fa3d8396ab03fa60cf4a2b55d 100644 (file)
 
 default_action :create
 
-property :plugin, :kind_of => String, :name_attribute => true
-property :template, :kind_of => String, :required => true
+property :plugin, :kind_of => String, :name_property => true
+property :template, :kind_of => String, :required => [:create]
 
 action :create do
   ohai new_resource.plugin do
     action :nothing
   end
 
+  directory "/etc/chef/ohai" do
+    owner "root"
+    group "root"
+    mode "755"
+    recursive true
+  end
+
   declare_resource :template, plugin_path do
     source new_resource.template
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     notifies :reload, "ohai[#{new_resource.plugin}]"
   end
 end
index 49c890b34a42c863fa5ebe4839fbb5aa2727bbf1..06a88e8b5613a9d8a31b353c2ef37f0b3e158f2e 100644 (file)
@@ -23,26 +23,35 @@ include_recipe "networking"
 package "openssh-client"
 package "openssh-server"
 
+template "/etc/ssh/sshd_config.d/chef.conf" do
+  source "sshd_config.conf.erb"
+  owner "root"
+  group "root"
+  mode "644"
+  notifies :restart, "service[ssh]"
+  only_if { Dir.exist?("/etc/ssh/sshd_config.d") }
+end
+
 service "ssh" do
   action [:enable, :start]
   supports :status => true, :restart => true, :reload => true
 end
 
 hosts = search(:node, "networking:interfaces").sort_by { |n| n[:hostname] }.collect do |node|
-  names = [node[:hostname]]
+  name = node.name.split(".").first
 
-  node.interfaces(:role => :external).each do |interface|
-    names |= ["#{node[:hostname]}.openstreetmap.org"]
-    names |= ["#{node[:hostname]}.#{interface[:zone]}.openstreetmap.org"]
-  end
+  names = [name]
 
   unless node.interfaces(:role => :internal).empty?
-    names |= ["#{node[:hostname]}.#{node[:networking][:roles][:external][:zone]}.openstreetmap.org"]
+    names.unshift("#{name}.#{node[:networking][:roles][:external][:zone]}.openstreetmap.org")
+  end
+
+  unless node.interfaces(:role => :external).empty?
+    names.unshift("#{name}.openstreetmap.org")
   end
 
   keys = {
-    "ssh-rsa" => node[:keys][:ssh][:host_rsa_public],
-    "ssh-dss" => node[:keys][:ssh][:host_dsa_public]
+    "ssh-rsa" => node[:keys][:ssh][:host_rsa_public]
   }
 
   if node[:keys][:ssh][:host_ecdsa_public]
@@ -56,22 +65,15 @@ hosts = search(:node, "networking:interfaces").sort_by { |n| n[:hostname] }.coll
   end
 
   Hash[
-    :names => names.sort,
+    :names => names,
     :addresses => node.ipaddresses.sort,
     :keys => keys
   ]
 end
 
-template "/etc/ssh/ssh_config" do
-  source "ssh_config.erb"
-  mode 0o644
-  owner "root"
-  group "root"
-end
-
 template "/etc/ssh/ssh_known_hosts" do
   source "ssh_known_hosts.erb"
-  mode 0o444
+  mode "444"
   owner "root"
   group "root"
   backup false
diff --git a/cookbooks/openssh/templates/default/ssh_config.erb b/cookbooks/openssh/templates/default/ssh_config.erb
deleted file mode 100644 (file)
index d1e425e..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-
-Host *
-    SendEnv LANG LC_*
-    HashKnownHosts yes
-    GSSAPIAuthentication yes
-    GSSAPIDelegateCredentials no
-
-Host *.oob
-    HostKeyAlgorithms ssh-rsa,ssh-dss
-
-Host *.oob.openstreetmap.org
-    HostKeyAlgorithms ssh-rsa,ssh-dss
index 5a853562cd02e01e7e4d2295e68a126d6dfb4d9d..2ab2e41d9372f84b5cc82ee4ccd7137fcf1ef114 100644 (file)
@@ -5,64 +5,64 @@
 <%= host[:names].join(",") -%>,<%= host[:addresses].join(",") -%> <%= type %> <%= host[:keys][type] %>
 <% end -%>
 <% end -%>
-ridley.oob,ridley.oob.openstreetmap.org,10.0.1.3 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCohCtONR/6e/RvHnLlSbvl0GqY+EJeTn+Sxu2PyWsw+W1OAfa2jmb2DQg7S54CwbkyI/owJdVrM8Gj3s5CVOi1kIddu7+pbkqrIZKo4Mf+jviFypyZoGYHnPSBwEfgAWKtfBepnbW2RIZ9+JEXLjUyOFwU6jT8QnQMKJc5FiDP3Q==
-ridley.oob,ridley.oob.openstreetmap.org,10.0.1.3 ssh-dss AAAAB3NzaC1kc3MAAACBAKzNiUprAK/uF6ippll2gTyE7QIYg8kcE1a59/4iyyh56ChG3W4bq8jgA6ZLvJRks+rbKnjs98duqFKFoGC7sXmvNvLGD7jtSbAUkiPzNUsQ1uwPatNJk/mY5zzHjaxmgOUfA0EtDxKgvxli0atn8Xj8PGy49BbtlBPdnS+tItQ/AAAAFQCO2II1Su14H1gaeU0ogUCkG20ePQAAAIEAo0+0I7Ha53KM9xJWt1qQAVTV3FTGrOwrmedpz6JYcyELhNhC/ZUDOXu5GKqkp5SRcXZ9NRV4FiDMZgKvMGyvRcF1ZOkytNGtx12FiXAzVsM55O+hszLouqZocJVXY6Km3SKmVkymGi+unoowCHWMWJEIAjz80KyR7dsXHQKqIXEAAACAdlDbeOLTQLcgwTGRMbJR63fz6zvQQMZVJ3DDYzQxiW/0qB2CeaB0CuS9DDSJBLVlp2C9MIVnDxxaQi1KmUOvNs2fqb0NEZ8AQG7clCASgf9nXN0EBju+dZ+lGcB6c5ZIcDB/z0gFEp/16sHe8bay70Zp+S4ot6jXD5UM/pLSmF4=
-urmel.oob,urmel.oob.openstreetmap.org,10.0.1.6 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/Z50neDHObFvqY7SjrvtebendKtlfZ5KdpUHJXzootFg5zli09HaMep8YuEqBK9n1H06qnLQY6Hr3tKUEMBjjn1VS/hiB3OQlAqci0YEqcgwyiBTz2Etkb7lDXgJVDcFA5Pjj5sKnXw7gi4Nmkgg6cfQb81fed1ySGArcFY6PFQ==
-urmel.oob,urmel.oob.openstreetmap.org,10.0.1.6 ssh-rsa AAAAB3NzaC1kc3MAAACBAJr/RfX1uZxsD/wuhnTwManZnbVET7yjqGx9H9oVXgDfGNDpk22U0/7VKh0BVHi7iC6Z92YWgCG2Os/SuZgOLqXxdJAjZv9iYqBFQBszzBjGpbtpmOZPzi4q/B4KtXmsiWVPk/eQoW7JodeaalGEflJbYY4rdtfNhWl7uR79NH9lAAAAFQCGJ68LbEk6z0t0fV6UuM2C3KDODwAAAIEAilB3PdoejxgWtd5zVWfK1pYooWyplBp0/qkQ/WV1sT/4+LsuDk1ttszD4DkyvSFwgXKULdcWl56YI2+rFS9busxyNVhM8u5ou7rMvL/laNqkruK8FGdObo1CrpqNS1CuTEcZnIXJcz9grYdmwx9Vt51V0TP7ExKggijX0FmYN4YAAACAJZy0ekCJk2l2kJwTN6D7J4NLIip4Xyv7YZhOuguhEXjmowQrAqsXRyBED0cMdC4DuUOO0AmbLJ7cw/IJ9rf5d87ZVRx8EBaGLd+WAtDGoSsLnYgY9iRWpKkYqfhLAwSfXA9d5iO1rh+FWngLsCBJ3aDurJvQHCw/xVai76tnWTU=
-#zark.oob,zark.oob.openstreetmap.org,10.0.1.8 ssh-rsa
-#zark.oob,zark.oob.openstreetmap.org,10.0.1.8 ssh-dss
-eustace.oob,eustace.oob.openstreetmap.org,10.0.1.9 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9wLWa3gAdXL/oUw67cLoHKiIOd959u++OOjXLR2OcyDkSLNTQgYkawEOcNgRVBcLjXh7ej9ktuTFbLWwR/Uvx7ftP5MH0Luo7Z9CvrQjw9Eu+G/CdGzvilHSeSAdCJYWemHXqKT9Qo9zJt2BI7wRfkFKdA5uXezwMYQtiQRHMkw==
-eustace.oob,eustace.oob.openstreetmap.org,10.0.1.9 ssh-dss AAAAB3NzaC1kc3MAAACBAMaxIrNlpW+VWMGGZ2NWdXC5Dbub7WluWXVf0kNwadZcwqn60wchAUDWnOL6grGjmYNPuHLW1P7tromy/uAssMML9YiNhCbJGUMF0IDWGl7bGjoOBsdp2slRaC9oZEceXH/yaRZJbxx9dri85WFLP9hz2A9mgi6Yx2k5oc4b2jr9AAAAFQD3k+OjolSAPwhQcYB97d5DDWjiawAAAIEAo7nRfP1i3VC3ovNAvY/SlvIq6iGorlkg8kMuBdTb5HPTPR8kOdplHGQ2+8es5H8a43GZorXbaUjsrzlQ98OzHrlw3BEzFvFZgY0kJwD64aeHOsDhltHzWV0tLz0Al5lR2ZpAE7V7Wv3x3wg3a+d9pmGkkgSwAqVQAsbPTp3wma4AAACBAJnhfhHZWrgNNnagbn+cuPpIC8vSwp/GNKK6VoQm7jq1u4t4eXPqHDuNA18pE1ngqPgZk1DYQUp98G1zKlhVJrUYHqi6wNG/qBMN8NuOyDeJ3a0iO6XIccEHvS15xzy4hpRerrg6yFeIhwZc1MbsEZqnPQzB2nJKtf5BqaeOjmcN
-eddie.oob,eddie.oob.openstreetmap.org,10.0.1.10 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+CNWzEucmDqWDAP2yq5gNGq1yC/1h5KohNb2sxOkac5RSij6/6UumO8tiW6PVY6wmiI01L+6UyRIfxWzqD/p+Pm60fNGJATrUsED/EEEbxKppWqbr5RjQfmfRqu/Msv0/QR1XnCEiEH2ixiubBBN8091Jn4m/GpZkLkcizpwOE3w3/FtUhydhdHgRKxQN8Mvu/pu9/6DocI7dNWEKWVUG8gbktUHe4+gHW9RQTPe1XISECt93i1NR3DKD2ldbtZbVeo9H0oRw1v9hmQdKXz6MUBQDenr1f1nzVmMqoLXJkdO2xBh2H9a6QME63nT+eO48BT/fo3VHomqFrR0MceGJ
-eddie.oob,eddie.oob.openstreetmap.org,10.0.1.10 ssh-dss AAAAB3NzaC1kc3MAAACBAIPneLfNaMa1qPVwRTKArXULa3ZRkKxia22DdT6ajV3HB9c0vjbMsI08vjjx9nWk2YWsZVuxx2kXi92o7uPJabFrstETbOv0TGTj6VVWThgGAqa5k7orMiSPOvyLPP3E9BOdf8nRpSPIq3cs/cBi4Oz0sPvbfljomXhgt1yC6EoRAAAAFQDqrUdtdgM33cYRUGqZ4MmZuyrHawAAAIATBEq5xAT0fH0hUJ47EBV9LRyi4kJfMyBlNwrSthUdIXhnhUTsO0se35I/1NOQhTcyI4fD+ZjR8qyy5SaR/QHFar1RKUksVa1S5JH+EaLHMSEEcdZCa7chx4Rg3UMJIHEE9zoPXn7VrbiAVtHck8IY/yIrSQpznIwuZGGonregnwAAAIBVv82Vkry8ypz8o/na00b03+n2KWRrkkWqKZvXSN43zVV6GQuwpgZpDjA6bLJjAkX27H2+jYB9QO3h/r0NndV7jkSPfHlCYgOg1HICI221Bnj2r466Fz0UdKI/wQqkJovJzNjrvwfESUqPfeTGGGo8AbyLlTI/JEUrHADmshS6LA==
-draco.oob,draco.oob.openstreetmap.org,10.0.1.11 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgHj1uavQKI1MXJaspRJasiPvhrM+EB+p47PuFh/BgFK4P5DnirS5sfApEheuGY7vcIiBnG2kcpNLiFmVylYXG1DbvBXsN0zLyJiyegdbT/SFjMq6AXyBfqFOA5na977JmJNBwzG7Z7jjeo4ZowRMSyQ3DjmGdj6vmSyT/BYO4E5Z
-sarel.oob,sarel.oob.openstreetmap.org,10.0.1.12 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCohCtONR/6e/RvHnLlSbvl0GqY+EJeTn+Sxu2PyWsw+W1OAfa2jmb2DQg7S54CwbkyI/owJdVrM8Gj3s5CVOi1kIddu7+pbkqrIZKo4Mf+jviFypyZoGYHnPSBwEfgAWKtfBepnbW2RIZ9+JEXLjUyOFwU6jT8QnQMKJc5FiDP3Q==
-sarel.oob,sarel.oob.openstreetmap.org,10.0.1.12 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgQCXV76oba/hqR50+HL1YjMeMPjBj8DfyNPcuEJwSO+TFbn4IW4xkxYYl3w4NuD8H6gj2Myk55Wza5BIR0oTWtuQuGiAKld+sIcMb7R2rT2KustEVuvy5GM1/NkAJ+sUa4lTTl64KPpFukFIC8Ma4hiEhXA4LnN02DZe0NdvyqkC9Q==
-noquiklos.oob,noquiklos.oob.openstreetmap.org,10.0.1.13 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDE5XeF6tG4hu9M0m+JWh4QJmL/52+cfeXbV4qfWwdJjSH9yBzYP9LiDM97gMXMUSnomAs7GO0KMwEdO9xuIZWeYFyHvs+1a73fAus8bcAbrZPuFfPfrW3JHKtWsfhUqYNJuRHLaimLIRyqgsXy3WAHf35v9kY1DmMWkf5/VTrp0w==
-noquiklos.oob,noquiklos.oob.openstreetmap.org,10.0.1.13 ssh-dss AAAAB3NzaC1kc3MAAACBAPK6Av/wAEtRnOx12117EtAhBPnodjQur0/k0pTAaGCZNnLY3E5SD7CvSqtB+LhRO/VSHXl1Obkh4mvR6oKEDE2XOWEG5Ofq3mWngT9Ejo0Rretzc1JU7L6WPZ8N/D+3kQUXpxDYzK9CcKz90k0msZUFRfGkHVE12ip9f7G/BWPRAAAAFQC5wUn4ZkWjt0z+/bUUOe298i0QvwAAAIEAz6dx6w5equWz3T8DWPM8LRGhE6ASrwR2UNpFe+sW5EBp/M+Zgg5Ztne1nIQaDSh1iKL0qzSGYxTIb/sIDKAxy6CzTjEhWRGmuDRTPQkXwD9iXcNaLChEEP6AryrI193LnLKRGKVve6gP2vH4tpn3Ve68HSKL4Ggz2L9ysKxJppEAAACABSHM7Ez/2oMaDGNRvgWc+ViB3QZOB1CTnDOkRZuhZXFMmTGXaWPzlwqPLZKg+wVOnJgBJ4BTUV6WovPGPYWadNuqhlsKjflFQyYSkyBA+4gvZ45TwbDE4HTQ1BGlXJVA3vq5HAqcxlo2CAj4HCQJgVHzd7sfH+WwyruGDu58ThU=
-errol.oob,errol.oob.openstreetmap.org,10.0.1.14 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA1riMj4gWqiovniYhlFNUxMm/AGmV/C2GjcMP+NcJ1ZyP4OdytGeGfhUm5GwVwraimkFQQlfEDcUWY7OX4EG115E8i15cUt6s6Ya2E6AXydigvBbrdp8MNnPOWBifVN3/5Cgi8nrAebmPs88ZZx2KM/Df5qIB2rHYpuHYyl+MpqE=
-errol.oob,errol.oob.openstreetmap.org,10.0.1.14 ssh-dss AAAAB3NzaC1kc3MAAACBAKcnhyMz3C4sku0e1/nFailjoPcMwLazXq4H/kUsdlt+f2By73F5KdUWffxoeRNL0UVT7+VCKG6IXmXGkKVfvpTipFjkP1N+b7I4SuJcQ/EUNPTCGAfC3l691K8jUBD6WSlQUqZtKGnpDS1zI/ZIYiNqrQnWu2RTYnP3QvY7JigDAAAAFQDI6aaH6mWx7vTVS9m3tyXQ4GQ08wAAAIAQjAM+q8Hfp1h45UjTeD2jIA74asQl0M+4q+4EcnNPnKXRbEBIg4rCWkHdd06uhayXZ91KzCDcj1b2LSb2zOE4U1MDEpdVnz22PuEl/f6/epKmLOqHoOGu9/9Lud6OoZQSveEPYmcpEEpt1RCN9ZvkVtFdLwtQ8+CSSGXg8yfCxgAAAIEAjQztmG1LN/e7pNRY0MtV148rJY3mR2knJegg0yBOEWHUGtKY91lgboWie1YTGR3RiXckJFFYkOGWAxqEVM//+rW0hatCxEp/mWEt/GWKPpV52fc4BUhJbi9hb8sg+dAvfoHwUL3CzHzqapaRNxxbfest8dfvascAjRDFP7yxU9w=
-yevaud.oob,yevaud.oob.openstreetmap.org,10.0.1.15 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAuWeUQd5ssUd5VFyTMXgC+U6c7s63mtuEj+cL6x8EU8PqNS12RGwLpeAI5VL8UzM0YLyPjPh/yzdQN2tl9ufK7KZF0apvoSZgp/uwyG+CgdFSf66nTrZN4NA/QP1ikH3kbqcM87LfNjCrMXnqMBJ/OCqz2z+An8t0KGDXS8haxlU=
-yevaud.oob,yevaud.oob.openstreetmap.org,10.0.1.15 ssh-dss AAAAB3NzaC1kc3MAAACBAL6RC7IMuQEtD4JIRmBJEownC0a7ZEvfCTw20PV5MjWb6twZlGBK3IA/0yV0oJ+75W6VWizn3cWSBS3y1zD8KktF4fh4+FVyin9WTyFuwME8cYmRPV+kuOa1lF1sLJxqvZJRjKMjweLeNTKnl1mb03049SL2YoGwMOTdVgVBjEyFAAAAFQC7rQIvnfLYbQdX87DwlzfMDALOoQAAAIEAmAu2kK8atEOR1Sc6maxYKSf68MYMHoTpm2MW9q2x5ls982kfEUMJ3h641cbRgOAuCmQU3gHnt73sl5LY3K3oLijIhSQm8+l+GkrXVhdwx7ScLXf+8TJZRWiP6Q98VWM4E3L4wmiJksLbTlxdoew3lv8gGhbpk0XuSyLWIBZIKJAAAACATogkqFXhPFzOMRJAR6G8J4bOqg9Ae2cGtf4aMZ9xdm/Hm7YLSu3kn5IhawwU+DL494VF+ky69T01iY3e4m/kQhYB4emlqsRHzVscblVH+GL6sVEkct0HMzfqzEFcfYWqqMdig9EwTzHwJzkAb4WqZdGnWG3Ln88x3liyDZTpGco=
-clifford.oob,clifford.oob.openstreetmap.org,10.0.1.17 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCsCrNQ+QQg2UUGhBpgjlLAF4gI48VDGmcF9prulYDxduyGJIrqhOjQtKLjNksMr8TEblmJsI4JzPf1lY1rVL3Q/aZWJD5X4Q0DgEtNzfinI9JAy77JASj1osBPU2RfWSvK9C2TnEoXHxuyGKMw9iuuPLppNMjZ103PYprQeAXi1w==
-clifford.oob,clifford.oob.openstreetmap.org,10.0.1.17 ssh-dss AAAAB3NzaC1kc3MAAACBAM+YhVzoOuKt/0UrkDpWCsDgYKPvbfuvSrLeyZfssRuRP1bVsY39yfl5avZM6YwYhzuyRAbcOLYa+9ien1QTeTbV2qNogx+/yt57DWKVv7nX6WTSVfYFAvx+CMy+L6O8N6VnKXJaCcbQxOFx74c0ysXorNYU0c8++KyNfMmVVjJ1AAAAFQDoCl23tnp1pcVbUFAAxAEUb77aAwAAAIAOpGMpxWPrd1y+IxLLLCohRMCv7JlUy324PMMwNx2/u2fF3oh4kL/EUarD4/6iU1n5PJo441bLuOj5Mb58/O8qdWYwBjbUoj1CiA7qF3TXWGmPX84AlwwLE12TIH1sTRlZTdrD6+js1KUUMSzMz8tEi4tJs+bXYf++ng12sqP48AAAAIBvm/z7yPKGdLPP9i9LzWShLJKrbY9zx0BOsIzzeVJjShdyB4+NZdxQR1jjDcqJ+r0DXtanmhS5DLOS6zGYfnzzsCNTxHM/Ne0wF4goc4LQGKg2aClmyx8ZvqwF96d8nQcUIbLUydbE32xmh0bIbzVchLKEm5PuNYf/aU4snCyDGQ==
-grindtooth.oob,grindtooth.oob.openstreetmap.org,10.0.1.19 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgDwRqYuKXX3gENA5JHkVTBEL5MxC0N5Re0uX/hAVTv7AurDlJyaN34ZdK+k89XjQBPNMn7DhwA/+ddXCWg0Bb4KEngfKys9oMhZcwEWCD8LFWJcKugATfFHJPtduJrMx5dNEfQtpA0od7Ep6XamGcJ/Hwxa5iQRlD+8Kr419qNTY
-pummelzacken.oob,pummelzacken.oob.openstreetmap.org,10.0.1.20 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEhjC0AfmTSwq1TgcwvSUZgzGJp6fP1DXkYfgREfgX6MQX0uRBTLgWKM1Nz2tYb14mjycJLdCjSBCzuHQg10ufX3+5nzR+xKIy7cgwqkl6I5/jX7BZNK6t8XZfdmwnhAhLqYfG5FA49eyaVNdArgHu1fv7xczKjRAMOlKhh083038bCD8BYmBoKwj2J6D6fp6wHOD2UU4rvTP2nCEYsvTd6s3/yvTOB2bFhz2qaqOhdNI1w+dvcZLPUYO5hdndw1LGC6v56IbmMquxcieWuOtU+fbTMnI9teNo4CLPVEzb3kmwhl4LyJEA1Sx65Bz7Ve4wfgUInPoBfiX1gdSjAqH9
-pummelzacken.oob,pummelzacken.oob.openstreetmap.org,10.0.1.20 ssh-dss AAAAB3NzaC1kc3MAAACBAN3kGdbPfrsSjQuX+9kk/an83YUlJ+Yd4V+AYbRrMRYBJEIQQOYxFOFwMOdmGRIFyLj2ZXKuYY3/5UFXHFeWZxqY6kWJ0JybFfOJaZu3Iwgh8gLlBnfkRWAD8WbzvXYTCwg8yrM335tj550AqrQ/6R09l0jveeK4EyA2w8Afdle9AAAAFQCOclxhmRDMVD8adpeBrpXJ0q1SvwAAAIEAt+0ZFeCMnteeadmiCrVbHpMot2FRcem87KouLdNgdOxOpuizMJgSSHEXBA6IwvRAzrLInpm/DoCdW+bdnrJkq8qs4gEhM6Dg3tDAiUz419S/sV/uZZb9O1aN/MBEzfysO+hnxemQvmQiA1vymhWov5dNl78UwFzETUj9xwW4kaUAAACBAIgjeLkkakNDkSRAYYh0X5hGjExvYRerNWdZ6hQsGKGlf3Ud0sUkKrtzpYUvWFQLnqniQXs9q0hTTxa4rVWHiCU5+R6gBOk5VgoVyM+evuOKFT5a7TorE5STDII+PQFSHQ2dJR2QsVaKmNbcSxQC+k3ttC8vBEAmIOl28m+QZ9kA
-grisu.oob,grisu.oob.openstreetmap.org,10.0.33.20 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDTEivJ/aHG2g7TVGEXJUDcOrbQKMOwYEzWiKvMTsftxOKqMW2uKzCZDkW3BNXIBiAXoswaqK0qkh519i56tY9ff7XjH5YoYbPyWwbhMPoBlIc6wBF+uMV3dBRrb7iRe0HFhpl/XsTo5vw8x+5T/ITrlvI8T7ZfE6uTLxKFDxYOiQ==
-grisu.oob,grisu.oob.openstreetmap.org,10.0.33.20 ssh-dss AAAAB3NzaC1kc3MAAACBAIrAKvS58z4zmaRWwebJxgUUiy/P2+AWODjz2FcqspmkXXnSkXD/tz3djsp/PwgPUPt/y1J+H2dfDY0qnTtY4SM1DJi0848/BG/C1P0zb/3mdtJO2FdMVVcwITCX0XZg7ikFf4zZ9CJRiuAbiS6CKCIXcvxHhBx0O4EEaK5/PwLxAAAAFQC6Rg2wsfl3aKpecSD0ed9Ysekx8wAAAIAo1yE6yLCH6+4NEA2+2mz3XWXdf/nzOWzFd1XqZIqg3Jj8MzaNS1GLbm3FlVwl7qlXr60flsXggYkZxwXyLKMH9fhFnyrTZOJMKmLKmeqcDTZqItW7hwsaKvM1vd+ZysmOVkFiXKJuD+25AyTmbFpNUvBdIHYiL1jQaIxLEWnN+wAAAIAuF7tHFgLgrZ84nc3Yb003llMmiwwaSUjF2t9y81t+FJ4fOwhFO7lIapijrsm17v5OBSOgAONfgzNS39U+VlX61PwDmIobe8+Q8zGOv/9tkK79YwNsG/dXhQ3e7gZH4wcyNgO1BufEuAOYMxE454rbv6fdrhvsUlRgEvF+teJqrQ==
-spike-04.oob,spike-04.oob.openstreetmap.org,10.0.33.21 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgQCIrf3Ca5+Cyk7/QYU2krboxC/qhHwjvtzBpcAtVya4YPpkiQa4G5KrJQ8oxvLL7j1atgYs+GnErkeUp89SLLMJ1spbjMMubA//Mr56Bp/V/ZCr7uk6c67vA+P+EIb9QhqJt6eay4fFZ75dccw76GnDunD6ADf1VTzawYykyIrm8Q==
-spike-05.oob,spike-05.oob.openstreetmap.org,10.0.33.22 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgEvdV6XL4KV/RCLZFhyM6sSGOWOia22L2Ddc28mS8MdZTr8b/iYJpFUCmGREovFxNI5MXzPhDKTomiW6UKmoxhQcsS31Y70BdsMA+XcNqwktFUkFfXMaat43gJ8gL5lVDI3AomjxIfGoouFEhIzTrj0JYMNf/q02YJm7fPvAZtuv
-katla.oob,katla.oob.openstreetmap.org,10.0.33.40 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgwCIJ+bSxbMsr6wurBXYkeqoznHnJT4zrN7nHtajgs5CJLIiWO+Eq/Lp+egz6Irxwk3v+kbfKW9RUum5fOMfkWFwaQxP41Cz5RbMmu5Jsm4MQKr4PPVxbLbPk75OeVgo+nfkzBupsBuYGMp/GCpjTJ8rusPmYxzWBek4amKL5udfA9Ld
-katla.oob,katla.oob.openstreetmap.org,10.0.33.40 ssh-dss AAAAB3NzaC1kc3MAAACBAP4oHi33lAVyP8zjoRZe6kxcZGJi1JOgF1vpZqEsxA97yCaLGVjc2cdxi16namqdJ/DgQaRpGRM+chP6AgGN9FD8Z6Wfskm+2sghPpcGRUkr7u6mM7WlJ0xQehD4LDcxFEpZKxtalf6TlxXn9cO0VaL9NNVrpU34c2Pqxl7wg/QnAAAAFQCB10EQxYDOnsxN2xrSHEbmgA3K0wAAAIAWN0b4KREM6Uc6FVkRtOjkiAR8FWmCg8nNQaqlKIPlM4hsrIcPC5yZfc7BzamQSy4PpHNGZG64CkYr8tn8LGWouHVKKbeFOWEXIBsRBSf1NNaYI7cS7WPnGVOmkt6yHvWwPlDcVO8FpPUL9pA7kf6iCuQNdD/MyOBHdbVoU9LcNAAAAIEAsXBb+3EZhsRAYL9Jm22PsrsW2o/hO7aomMeEXvVGG8Wuy77lqmcIvlyW3zhHBs7ubI9TZz1XDsgLK9giCkmqCyKmUsTXGsu9e4veOq+sgvXdbhoBMVi90IFsPLPUdPN5mfovBDHkwi60VtDwOLAX368pFfBfSA50CZWfhwUu26E=
-thorn-04.oob,thorn-04.oob.openstreetmap.org,10.0.33.41 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgH5H4Ra0f4+LfMyJbVpoJIN9wPrC0bbNEJUVIOmtPpxRE4HvoqDOBE8XfHIunhNeTxK5Yzfinz+fCq2XCv/8Sgrr1qJBUQwi9kHfRBNmRJyoylxY0b33Dpsk5kxcAl06+sSugl/OcbXAyW4H3d+dQAUMlRPEVzQCgd98gGrTFF6p
-thorn-05.oob,thorn-05.oob.openstreetmap.org,10.0.33.42 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgQCYjNImXo+2xnRT7T/JiHh+eNl8I5i/sjB4KBaHizKuJnwH4heLbPtmbI9ze9MV0IHJp/289kwT3bSgj0nY9zi9Ucdry0WtPgGQO4JbDZXzCBhwa6MhZVLAIOKU34fK6AIuZqzQJwXeJZuCIiwaoliUwY+QwNcX3rQho80eaK6XFg==
-orm.oob,orm.oob.openstreetmap.org,10.0.49.3 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAn68BVVd15SyHq1vdXYZukNkoxBPlNBgA8gcaXjlQg917A8gXcHaJQ04xSwt/jkbbvELNuvYDuw0EZAqQQHG1vYsXffg8bYrEq/WUs2+oc1O6iiR3xrzgDWAdefEVk+Fk8TXRGI3dy6IBpFoQ6ywvNCbFvVcB41FLRtBGOWdJFZM=
-ouroboros.oob,ouroboros.oob.openstreetmap.org,10.0.49.4 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC0b16+oF2QHYj+iIS2YT5VnH8KfdYckm1ujYSo5WitGONMqhN872W6krqYbW7GjFvrJ2d7GbNaY/3VeVURLumgWBnit77bExpga++/QYsE90DSoiQMeUT0Q4QuPWXcTIzAcGesda4VtQkTRBTt1UlmdEGBP3eDAqL2GoW4DBPCiQ==
-ramoth.oob,ramoth.oob.openstreetmap.org,10.0.49.5 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgnWJq8z9xvNFujhE0P040rCO1yEsH8pnQmGOGehIRcfclQBd2wOO22+8kpy04BMT9FaFdxjgNTUWtfCwT+oBsxbHIreahld34vFVCw/VSCiPEuUhBdZ+fN9hdLGygrnKxA1b2cIs532nm4LLDoP2VpM4RZuh6da+LV3eHnfDlZHO870=
-ramoth.oob,ramoth.oob.openstreetmap.org,10.0.49.5 ssh-dss AAAAB3NzaC1kc3MAAACBAMjYCKyJfA9/EQWTxwqqGBq88dAaWWG0j+ggoGEYuIWqcdA1NeF70BIiRGvAV5/oBy+p/snd0LAxDG6KnWglOo/0cjzcfys/RQl9kTa6gkcFPp9lUqRnuDF+y/egZVTU3KF376k930nNdODMe5PxECnZdC51158Zga9Hwj0+5nalAAAAFQDnh0Gx+gt+6Qc1r74FeNCiIPmzIQAAAIEAs81g5c2sF42ATY/gd5ustNXm82xfIAuRGeMCgxyXBvFM5UXuLnfOx8JVB8wu9eoSmxhDiuVX7ija5FaKAAucPBXWh/YImH+T3SOWLsxfDh8XglH4NvEtj1r+90VWbX/f1Qy7IsmmBolUCr32qD5cdeQ3JPxvUvO/TdSHaIgGK30AAACAZiVJOiM9mfMf05rAg9fjo+NKxL/jsbZ8ptTnNOFBNjq0XydXQF3Rnt01b/cUSv94VmuJgv9hq9L39nk/dSnBVQbKwIYyB0/NR2Fg0sYHpo4qj+7MFndv+ct9pVd+l9pmlEoR8soLeO1hSVeSmj9YvDzc74lx8FYMVE6+yed8ltw=
-spike-01.oob,spike-01.oob.openstreetmap.org,10.0.49.6 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDHhi90mKvMe+FL1pdzBPWUfC+a0ckv31Qou7Yby1Kn9xhrR5oHvyoT4bc/xPrYvaxRZUHWn+J66ZdylhyfCZf6/5g8xghJoYVAZJn9yCV0R7xw2fzHCgue3iS/Yrep2V3DRaXt/zy+PCe7wZX7InLLtp1rV/Vx2xG3lV91OGa4Zw==
-spike-01.oob,spike-01.oob.openstreetmap.org,10.0.49.6 ssh-dss AAAAB3NzaC1kc3MAAACBAOE5d8RsNmFZxWkcwXHisg5NowzVyvYjW/cXmDRkeN9r2gvjDRj+WU8CIo4rhVhbJIepEA/BUkzEyDBrBOydFa/pFH9KN+tRnSabRHaVweXr337KX9ltSGoPijSwUlDhVITMMSZ5v50tJ9bokyZEYbgpbzPo+slqgMFbR3fr1MvbAAAAFQDWzbv+xMTMOYcQQ92MCaQKtsXCJwAAAIBW02qjzbss0X9TACVhGHGbAy5DcfybmY8JZhfUgqR0xI5rCufUW5+dY7EQu3FlE8bC/R1rPrks7wngmut6xPMtkpcpMYFoxFPgP8/xfwkTNYMs2J5Vbrb6k6e1XMKt9AID+QzhEjTVxmwLKAT8uZGDZjY8ujYnQMbM3wPbCbv/MgAAAIB4xUK2Of6YBWBOpW/0GPfFH/of8Txv2ErpVmTSTOFaO7KD6x4jcKjn9nFMvVUhW/c52UYYcscE6uArd3XNbJBw/H58i26V8RooTkQVWhKNbp9ktXPh8yADNzVq/rRW6kvNYHZbbTev7WZ0NPvz2aIrTLKPcEcUwLq4wpNBe//1LA==
-spike-02.oob,spike-02.oob.openstreetmap.org,10.0.49.7 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDJfkctRhGPVyPY18EVcegsABPTC7PsCA6Pt2UOkkzANJKkwrOUJyn5GqgJYHkOb3hWqPlS89zdlV9kXlvTdUZ8QKw4xys/5H5+CWwbag0h1EpDR9S0xO9gIgX5DgyB5Y7oNS8o9AolF+hgyUdmBYO3ff+h7eu1PnqBn8TfquqVcw==
-spike-02.oob,spike-02.oob.openstreetmap.org,10.0.49.7 ssh-dss AAAAB3NzaC1kc3MAAACBAMxbg3AjYJcMX0jlgyXslqLbi3MV1zAVunNGqFOipJCW3thZ/D780MbQiXuXglqJQxWsELy+8RVVjt6/rcnZHORsH2H8M0/3WdlEUW0FxMUISXUAVtto0Fk1v4QznUtyxoKIg7sXktmreaNEcLBA7Le1bOBf/Oz14uQbmI4nycelAAAAFQDEMSn6sAPKhEYhYJiFYsDoV0aWfwAAAIAG9y+c73QbYqHBOdNISG22W0BYAnUj1L90lW44xNnmrVOc+CdTKG3VnAQcIc5BeB75sfE29JOmUGfR3/clCgCL54V8D+gEH3omtSG3eG7B+OoWhcUIoIfgO/3w2ZactdU8lA2qwSfZ0p7xLPsrDN4wuORPYFpoOU/vV9hG+dh7VQAAAIEAuk45eD65i9Gx6hHQuCoN5EGQHhL5qvO2gbShYLNqEhkDN+TmdTLK4Wbevy6tOdCrCRKP5zhoycbqm448hINFtwBPXGfRfhDsAGm075pMwljlh/LU3lSXbSU1RkmiXqjYqcjl0ntxkv2qA+zN7G1/oJK85pwScyiMo9kOuwyh3+M=
-spike-03.oob,spike-03.oob.openstreetmap.org,10.0.49.8 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCvTY6CDpJgBcU5T0l7Hmn6UkLZw1d0EQEPlcQM1UvLfdSKayVR79Yl31eVWFbA+R+QqQ8LKcmzx6ztWPuemW3Ym/gZ7NNYH10y1Rw9LywWhVnFOjKIBUVJmjdiuxftyCPveHu672k1KJ+bApXlA3/oMBmtCckr2Wod2qJDx7JIeQ==
-spike-03.oob,spike-03.oob.openstreetmap.org,10.0.49.8 ssh-dss AAAAB3NzaC1kc3MAAACBAKHL6HuJER/kKOFoGbPvQ0ghCw5lJ4ACsZHi4ptTwpBh1rx+/mmktTU6/U+cP8ocGo2XIuoCaBMfNK/eqrh37a8/fZah5+wxwJBWnZqncOhJT9EjRfvRtbJr8GRtCukNxX554zsQBSqCn9CIP6E62EqbYUf0qfROX5o3SZVu2WzFAAAAFQCWHnuBktRY7R5n2ZuCL1Cdx5hevQAAAIARZiVCIAKIJerBY4AnGADzRf/m21PkhksRIKcqge8vDI5z8MMgYkmtcrlqgGPEavnajBPlAF8DdDFRbx/4k8K5ZZdr+4ipp2++V7fbkg6n2MMwR7qTN3FpoNtLwXSHLlsueAArRW3RNlYdtx9wZppUq+cGlqr0J8jXS4UOLH3MdwAAAIA3Y4EPZv6PufNBppuegYI/gziypGwlNc//XODoIagXyDclGxGnqh36J+AUWxuILQeHRTZzdLCVazFZt+EGJeKI7/C3yJOkSp3vNnre4VYmGGRp1hcBKWDVCltjv+phRMXGiuGSQdqCy+AfkGSctNQafRnQuaL5hLBytHxbXIADhA==
-dulcy.oob,dulcy.oob.openstreetmap.org,10.0.49.9 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgmlwXGPIPDqoMz4s5edr+G4iuBnCYcFXjY7Et9jG/ezI6aIKd9lEOXvnHJX5hrC21aqd06dhyMLwZN+eSjJhXNaLtYmm5P442H2ZnGca1KNSpF7yRVhn0eRpX39xWK3biVfMw64mzvV3636C1adCkgBwuaqCvz1EHm/KRrySfuETFLU=
-dulcy.oob,dulcy.oob.openstreetmap.org,10.0.49.9 ssh-dss AAAAB3NzaC1kc3MAAACBANcuNreghg/8rJAmfsdD3Rp58vN84Ee1oEFMgGSxF6+yEVTbXrjQoH632jiBXSayQLXGEzrVTsGaWgujK9xT7OinNa52ydnJ/WZp5qK5FdW95h5m7pnUE3Jmm2cPmYpEJW62OeMStmTGkK0EvN2wwRLuts9R1NK63tWjFWik7QmrAAAAFQDNtW3WKlCugOFZnjIh3fBuDakdlwAAAIAzy/pxXiix8yKhlb0LQJ1izilnn2IXRvAHv4aM6LAiq6QIDj2XyT9oTS/77BguCw39WhVG599eOSRckWXFgUT2p3pWBBuuDbLEhQqIc0KgufYh/ygUdjf7zs0O2jusFkLMPgF/0IgRs/ftb36ERn3KJ4C1P0v1ABk9t55Qs985WAAAAIBZFS2HS1ewjv+/jAdUH68zT0mNBctnrqM8ixqT1Xd2Tl7SKjl6Sz9yer+6+Gq7O50U0FBS0pQPo3f9msazQU6BFYCzuSFRIJQmH7uKGPHHA7mbuow6sEOhtXBzq1VfI4addXyWlYLKXxv94/gt9xlxLZHqU4ZZb3GPGbU7kKJA9g==
-ironbelly.oob,ironbelly.oob.openstreetmap.org,10.0.49.10 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgwDkRqR1VRgHOON8M7YCNnIG8k0zukAN/r4L5fPKTvWmdhe17UnxywPc+TySjXqNsXQ/jPLGvpO5uoSG3dgT2N7NUdAtdL4Enb87dX7yTbJTJzMMxTb9HSI1SL2/5iSefyAVVo1+R8DMmFqTWa2eFHoD9IoxFSNSTarTZQgmH1oZYoZX
-ironbelly.oob,ironbelly.oob.openstreetmap.org,10.0.49.10 ssh-dss AAAAB3NzaC1kc3MAAACBAJKKtKZBECA+wtvYtrEeMyTzkm3X/4IfC6E8NcnZouMCHYn3F964+pG7mRskZAi7P95VwJYx6TLkiK/MNKIh8mk8M4Xxu2USIXblkTPraPYHyVgTkfZit6F9qTR8cAOlHtoY+9GgKmWMLC+xeOgPtoERvUyuuprXsAztZ9C2BKWjAAAAFQDnPXN3n2g1xxsYZsaQpdPuijb1tQAAAIA7/IpFy3mSgpu/TmmBuYLccdRTCNt493U3wMLb/JdUBu4h1FM6J5DSozcQ70ATglpLLYa3Ru5ztv87Esu8c7CH/TAH+GZ5/3LJtS//HJDt+53yy4CgwO8pcKbYo0rfRy4/QdFXWeBUtM2XN4hHvbaBJ0fzP1gXI1GHvz3OQxWICgAAAIAvZVlk6GX+uGpqLdW4F1ctkuqUnkIGzRziJ9Gk46vOOFCPxU8bUXLGzvC7Zv3SOR04YH7/LDMUof2y68EOCbH9YT8mHNqLdZ9TxOWv8wUaDX5O9J8JXngLwl+U+ONitseg/PrEZKmP2/cR42pFwuTzb59+NSkEVAa0ZK6+2FkWog==
-spike-06.oob,spike-06.oob.openstreetmap.org,10.0.49.11 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDwQVb/cYgKp21vw6+jKr5TLAD77oKunbFbjvwPL34iLRDqdJcEOdJBV1A63ZDUWSWjDUrTa0kyneoiYdD876EpuspZ4bPgmiHBvug5NR3usxa8PAsia1K+fONAGi3+s96H6Us273KHNH5QwyBNDyYaDDjIECkydU4bQT0FSX0j32eAHI62ZO/H82fUyL20PIK/nCUaJUd+5iXgcTfjP+eL66ghgPCgXGF99/w2+3EUxP2IN9J2yI57H/rYn3rj+NdZyQuzc0TAToT341cYh2+a8R1Sb/DEFiMZFE2hJ2NeVEaBYxPSlFfhRtlB6ArXg5QL7e7UScQh/ZHLU26A1ZaB
-spike-06.oob,spike-06.oob.openstreetmap.org,10.0.49.11 ssh-dss AAAAB3NzaC1kc3MAAACBAKwUXFxncoW/AmYePSswZkqbHJDN5zI6MblYRtyLwSzfdthD8KCiDnoG+6opsy18jaX+sX0PTz8hfNVUPCMhtiTSgbGqZuQbriT1z8x3yRbGShqH1ZGC2Tt8x8k7ft17Z1tgnsnmueMrGekks6/kMZWYl+zrHXbrKCM4uPIHjK7DAAAAFQCOmXTNMg+q+8BybEEHDtWH0hbnXQAAAIBhZi+1jUaHu0UEtKnPRnChDyPrWXpgwVOM+goAZCOxfObI6PcxrIhB31gRPWNETR0UzMb2K9t1oCNdyyq7Y2TdFHEVHOTaBTWS5C9Bvtz8CHSou8mibH9sIhK2H8FevdQPOZHeUxQRSx+JzCL+f3qMovs05xVBNhUHO5XLtzIKdgAAAIAGlmX7cp+zx8D2vPiZEcczjJIgK2DvAu7t3ZAemcX5utUNKh0By7xxT8DqzIPYRvoAI+//4xqt11jIdO7KADc28uyv6oBAbB8DwhlbRONM9O84tqBTIxu0bQXtsYpkTAQvLlrDXMYDx5aYLpP1haTbGgdtjbDCz4FH1Qi7cBN0kw==
-spike-07.oob,spike-07.oob.openstreetmap.org,10.0.49.12 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCxLxAbMPZw+LgzB8JmTLLxqc6CZXYA3Wo18RM02+EnmtRX6AAf/VFb7E/VpgHfZecwnFK7u21R47+fFdHCb8EDYGeWbOYoEOYMoDh26H8/aFPHbldgG0xs9EwfTryWB7iZ2sD9nLv+nBpDkFXVq53kscmDlUKQrvUyj/zR55xGxcq0ruu3w05ZeGx5I6HRY0xeK+6H4s6sZtF24Zm3CttQ5M7ADgWffE35ZwA9tEdioM3J3c5EcV4HMdhl7wame6pID9+FpDEtcts5z5sfW9Y0yx3FHrXCxRWxHRbyFG9/+4RNwKJBRZrdb+VSLlrYVUFLEfb1AhOxr8ZfSsJU1V0V
-spike-07.oob,spike-07.oob.openstreetmap.org,10.0.49.12 ssh-dss AAAAB3NzaC1kc3MAAACBAKzH4llCRo3t5ifkL9qB1KoWcAw1ROGVAJBwE0GkFZRQvzGQ7CE4anpFdv8BVlUbFx9N6batsC00ERDL9ReWQXWMa1oHr9AJ5Prpgt+azn3AFrKhhkMQZegjnZ0Ddsl/XSmFbRbJX5cnvrSIBL5nEC6kBCVFDiuH8MlsWaUsvUtbAAAAFQCWQKlZ5osk9BZKsnss/W+Mv653RwAAAIEAmbM4n4Sl77tGuTQZrlojpjEF/qm4iUpnAwbE93e2EIr2thnM+6QYtzYZ6VXSXwrh4UW6d9lL2mgSxQnY1HiM37y6e/oNFrsluK5j7AhxAYm4bHT+UpqyU/zl3eUlTdvBxhkTjQTT+wTsBgTwu5zZaJrlEPzoYkCQNJRS5AAw0gAAAACATzzX9K2AYRf7h8gK90abOmp/LYNO9ghhbhifsIrIxfShsFubUSfRO+m9e9wG2/1kwQY2VuVpdM86wwFvjHFlo2VHQkIl1JkP8pmVKs/QKSo4WSDY7aO8bpQK2Xx7QC06PUnllgXsPcyted8BGCoTLMVRkmukMwWls+Qw4fr7z18=
-spike-08.oob,spike-08.oob.openstreetmap.org,10.0.49.13 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCm7BnJ/+IKh/uAI3vIjIlkqq83jFkuxfxPuMty9/jhm9XoVbf+nqTfRQ1zMZn+bqjEjLRFTU3uwsjI61fk1Uxru34JKoJM3axNPK0S0TH6Gh08oLoBCCOti1/tTAiYaSLFfauucnJeEMkKsmIaM4LzawphkIuWu5kUv0LteuycqJAXZKr4jAIYZuxQZ2e3ofdzQoXIjXbEg/9EWyMA+zbUYlAZpELicTOQywhpez+TpZ8GUnMuya7jv5pTWfiTbSkToF0HTrKUxIEg1HYruBs+0OYI+LbABe93z/fAk3j31y3FAPEnR7vqbM7mc4DLSwgtKsKkpGGGeVHLEJtHVhhD
-spike-08.oob,spike-08.oob.openstreetmap.org,10.0.49.13 ssh-dss AAAAB3NzaC1kc3MAAACBAKJKB5ukyM8DRC6fbpXb3KEqSq4CmBqrlqXCFaktWKFerKUJWx5No/xWn6n0H46FwpznH07Dt/Mom6XuN2A0i/ZD1pE0VHnQif23+L3PBu7t3cDPVJkj+eYVB2avPPrwLGhOLOss0oKnBwhOgK3FTerCRUN5MuczzPY8xtz7w495AAAAFQCj87X4s3sLxHybJmuRFEuc68Zd8wAAAIEAhajd+H+3uVBAIKdWpn6GoU6bP0y9/ERnz1GKp+fBlTVHT+eSc1E567HqVErHxc7QSFIBmdlF88MyS0izQSAFKdzevJWqUbDeUKtcB26hGGrvHOp1dLsoALpuUDhOZvKIzehp5linYJmgnN91piZ3BlyxT1acr4zdceIGNL7rJtwAAACAYlD2EQvr2JI99MooGimqEYP/zC/HhChmtCEIJ/XQrOuKxBL4AlegFNECXBMn4JHFbdyb59LYvVlykuCgLgNY2EKObgltKJ5WLmzIRpUTBW2TlwAQiRnGqA6TGUpTTlKZFqAnRSqOJfcvQw9E4HwlN5TeOT5kxN9j1duUaV5WLx0=
-tabaluga.oob,tabaluga.oob.openstreetmap.org,10.0.49.14 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChE4Wu5bUAgtJxrappT9kZeftw9gdj+D0QmisCGHbLsDxDnww7g5gplexQOf5aEtLon5NU4HNixcEFZ+/RtEtTuVaC7wAdNF1HOdOecexvHcEFlR6KPrdAKykTyo4hWYUd4Uz38zp160V//ViAgylpvU2dhGhAWKcxgmamNMz9iPd99T0fW9bXAzpiB+yBuBskD+JyA9bQu56mfIW4u4rh1xgPBRyUdorqetM97QJ/fcdkN0m4qVda9qP0J5DUli6Cq8IbEbv87r87VPV9o/WOKGBJtclXdUuF9aLAvP3p5V+OuxqUCtvy2r6LDBvVURURb2/VXzn0O9x2pWE6uPeD
-tabaluga.oob,tabaluga.oob.openstreetmap.org,10.0.49.14 ssh-dss AAAAB3NzaC1kc3MAAACBAIQNHSK0uo1CehCFag09Hd+bJ+CDD0LPWoE/6B8Ye3woVQw8XhJPIygWyHlsFo4rbgkTnvz4ooKTUHnisEIoAA6hlqFTVP1LQQarkmba5Gf05x42hYKjM6mYvcoDMAdnkPueqKIa2CQVNCg3sopI2isxaUUWPEqrVeTMgI40ofd7AAAAFQCSNIl/McB7R/7q4fFxZ2dVGtvJGwAAAIBNRHSJrnm4IDYufJetkWyn4KEIkycUMDs1WE1H1LbtmsIaBAGaz1QJKclPCin+hCv/Rne4oPoZWGl3SqB7hjBkvKUOKRaMp4eG1YCpEvAhgNIFjPkgdekctQ1H6/+7CkQmMVelh78cUMOUYEoky7ISiaKUT3z8O9EEjPIndreNBQAAAIAQeqPxG9B+RJtcOqnW5d9M8VVUNeW10A2R2AMtTEH+/hjaoXUPpL3bQ0Fl3aWQKYJMRpOM64GgLswEhxeWf0PzSAi5CwBmyhIEUJpJ0jHOYSUXC6sLpBMV1ad4gF/63CBAgL1fUnQ/FWDtZwDEnBksDbYSS6EJB5m1o1vOx3SHWw==
-odin.oob,odin.oob.openstreetmap.org,10.0.49.15 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCeK2EVK4rbsdoTq84Cl5kLhbJk7gbaNav61yFuSKfSsizzbH/tzxmiFA7mtB39WU/BlFsTHAg1mHY7cCPE01E811CDPIQhZGEyloh5ftbTACCcGAjKBhYpwTPEteBqlIk3lpN1TNTsnJSYaQay3rbOQ+IXTb8nzKYjTgANQ6QXxSq4BfuRmvMRlNw7ZuIerhs8OL2G/pxldL6AYDPDFXBs9mvvqqS0fw8rzxkjFNUc/z9odFoChtlZVbp33/LTIBQU1dY/XTxaekErjT7H93KG9NP8mmIFZtU8oRo8553ogTYVxFr6hD5D6KkbveaFU9oBDRYlJPWtdHksF8RAEpjN
-odin.oob,odin.oob.openstreetmap.org,10.0.49.15 ssh-dss AAAAB3NzaC1kc3MAAACBAMxXgZGeLxWyQCErmy0aGppk2/xHj3GTATPCQgf/Mtm5PYK7c3x8Z/fEop/BBnY2/YDE709g28Tv+61I4SD9D33OO6ABPEapHEwqp3CIYuA8+JFJhuo6Sz9h9bca6fx/KVjdDq9wbmx5IOqEFQlBoCSGJvYw5pTptVFN+nLeiTLjAAAAFQDt76BO4R+GaDn6/SeJvP3xAuqkmwAAAIEAgbhpMfB2Gk+babYDnWTWMkFO1FObUdi8/3NmiS1XUPCzdGkL1h2psoQIMXFtrNfEzSPx320rjC17T+JD1KGzXTBsPSd49MhznMc13JK2YT6KJm3io1CLKuzje4SxrpddM1Uvs/sOLmeAbdNqlUsAM8KUedEYTo/SXeVecos6dboAAACAasbTSjiTPW3NwH1yrEV8xWFCAmsmAPvqwGjaLjrrDdNQCbJ0KHMY+lbUAmT6oZ5qcrwwc2A6B+/v9XBISiT5XWELdP56bhuDcWC78aJDdtfDK1xuMtsHX5tpQcKB7IrPI+2UYVhz7zosvcCbn8FukgDx8sEcp28rHaFB5WPCjig=
-karm.oob,karm.oob.openstreetmap.org,10.0.49.50 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgnWJq8z9xvNFujhE0P040rCO1yEsH8pnQmGOGehIRcfclQBd2wOO22+8kpy04BMT9FaFdxjgNTUWtfCwT+oBsxbHIreahld34vFVCw/VSCiPEuUhBdZ+fN9hdLGygrnKxA1b2cIs532nm4LLDoP2VpM4RZuh6da+LV3eHnfDlZHO870=
-karm.oob,karm.oob.openstreetmap.org,10.0.49.50 ssh-dss AAAAB3NzaC1kc3MAAACBAMjYCKyJfA9/EQWTxwqqGBq88dAaWWG0j+ggoGEYuIWqcdA1NeF70BIiRGvAV5/oBy+p/snd0LAxDG6KnWglOo/0cjzcfys/RQl9kTa6gkcFPp9lUqRnuDF+y/egZVTU3KF376k930nNdODMe5PxECnZdC51158Zga9Hwj0+5nalAAAAFQDnh0Gx+gt+6Qc1r74FeNCiIPmzIQAAAIEAs81g5c2sF42ATY/gd5ustNXm82xfIAuRGeMCgxyXBvFM5UXuLnfOx8JVB8wu9eoSmxhDiuVX7ija5FaKAAucPBXWh/YImH+T3SOWLsxfDh8XglH4NvEtj1r+90VWbX/f1Qy7IsmmBolUCr32qD5cdeQ3JPxvUvO/TdSHaIgGK30AAACAZiVJOiM9mfMf05rAg9fjo+NKxL/jsbZ8ptTnNOFBNjq0XydXQF3Rnt01b/cUSv94VmuJgv9hq9L39nk/dSnBVQbKwIYyB0/NR2Fg0sYHpo4qj+7MFndv+ct9pVd+l9pmlEoR8soLeO1hSVeSmj9YvDzc74lx8FYMVE6+yed8ltw=
-thorn-01.oob,thorn-01.oob.openstreetmap.org,10.0.49.51 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgQCFBaTPsbNtWlUSsGnRzObp3NVC6MOro10p4qSXB0kwAB+hQx/IrIH8BjduR+b6Uv2cm/UMnGRzS/1lGYe15cSs0V/IOUyXdVeX+jB0TXzS4hTqclGKJ0Ay2WEsgW27IdPxIjQg/W77s9AZ2UlyEtT7gK2oergD60yUvRfLLJioYA==
-thorn-02.oob,thorn-02.oob.openstreetmap.org,10.0.49.52 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgEitEET7IzW9j0lgxcgXT9JgzDR/cbQdlYSwV6rcWvHW9cz1ArWmJ6BY2AJ6CG3wTznVbHPupiFKf0jvkX0omKu8K90f5FJc2/BkUP4aG72YmAoPVe4bflGykvKJE9Rd4BDyPWGqI955Okp3VGCEKXBS/fwnoOZlei+9ex334hK2
-thorn-03.oob,thorn-03.oob.openstreetmap.org,10.0.49.53 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgBrDGGrP1jST/axY9UTs1q0ljkET93/vIitbc/C87pe08ccQUL/PUn0GTrVhXps2Q2nfg2IuI32vYYy0lNKXD53NOpu5G0ZxEB6BYxwejwD5YLZhJQD1mtZ5JvyAPeeWfZa15ZRoI0qzg9RxzB5bp4cRKtHxFcGRAj1jjHkN+80x
+ridley.oob.openstreetmap.org,ridley.oob,10.0.1.3 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCohCtONR/6e/RvHnLlSbvl0GqY+EJeTn+Sxu2PyWsw+W1OAfa2jmb2DQg7S54CwbkyI/owJdVrM8Gj3s5CVOi1kIddu7+pbkqrIZKo4Mf+jviFypyZoGYHnPSBwEfgAWKtfBepnbW2RIZ9+JEXLjUyOFwU6jT8QnQMKJc5FiDP3Q==
+ridley.oob.openstreetmap.org,ridley.oob,10.0.1.3 ssh-dss AAAAB3NzaC1kc3MAAACBAKzNiUprAK/uF6ippll2gTyE7QIYg8kcE1a59/4iyyh56ChG3W4bq8jgA6ZLvJRks+rbKnjs98duqFKFoGC7sXmvNvLGD7jtSbAUkiPzNUsQ1uwPatNJk/mY5zzHjaxmgOUfA0EtDxKgvxli0atn8Xj8PGy49BbtlBPdnS+tItQ/AAAAFQCO2II1Su14H1gaeU0ogUCkG20ePQAAAIEAo0+0I7Ha53KM9xJWt1qQAVTV3FTGrOwrmedpz6JYcyELhNhC/ZUDOXu5GKqkp5SRcXZ9NRV4FiDMZgKvMGyvRcF1ZOkytNGtx12FiXAzVsM55O+hszLouqZocJVXY6Km3SKmVkymGi+unoowCHWMWJEIAjz80KyR7dsXHQKqIXEAAACAdlDbeOLTQLcgwTGRMbJR63fz6zvQQMZVJ3DDYzQxiW/0qB2CeaB0CuS9DDSJBLVlp2C9MIVnDxxaQi1KmUOvNs2fqb0NEZ8AQG7clCASgf9nXN0EBju+dZ+lGcB6c5ZIcDB/z0gFEp/16sHe8bay70Zp+S4ot6jXD5UM/pLSmF4=
+urmel.oob.openstreetmap.org,urmel.oob,10.0.1.6 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/Z50neDHObFvqY7SjrvtebendKtlfZ5KdpUHJXzootFg5zli09HaMep8YuEqBK9n1H06qnLQY6Hr3tKUEMBjjn1VS/hiB3OQlAqci0YEqcgwyiBTz2Etkb7lDXgJVDcFA5Pjj5sKnXw7gi4Nmkgg6cfQb81fed1ySGArcFY6PFQ==
+urmel.oob.openstreetmap.org,urmel.oob,10.0.1.6 ssh-rsa AAAAB3NzaC1kc3MAAACBAJr/RfX1uZxsD/wuhnTwManZnbVET7yjqGx9H9oVXgDfGNDpk22U0/7VKh0BVHi7iC6Z92YWgCG2Os/SuZgOLqXxdJAjZv9iYqBFQBszzBjGpbtpmOZPzi4q/B4KtXmsiWVPk/eQoW7JodeaalGEflJbYY4rdtfNhWl7uR79NH9lAAAAFQCGJ68LbEk6z0t0fV6UuM2C3KDODwAAAIEAilB3PdoejxgWtd5zVWfK1pYooWyplBp0/qkQ/WV1sT/4+LsuDk1ttszD4DkyvSFwgXKULdcWl56YI2+rFS9busxyNVhM8u5ou7rMvL/laNqkruK8FGdObo1CrpqNS1CuTEcZnIXJcz9grYdmwx9Vt51V0TP7ExKggijX0FmYN4YAAACAJZy0ekCJk2l2kJwTN6D7J4NLIip4Xyv7YZhOuguhEXjmowQrAqsXRyBED0cMdC4DuUOO0AmbLJ7cw/IJ9rf5d87ZVRx8EBaGLd+WAtDGoSsLnYgY9iRWpKkYqfhLAwSfXA9d5iO1rh+FWngLsCBJ3aDurJvQHCw/xVai76tnWTU=
+#zark.oob.openstreetmap.org,zark.oob,10.0.1.8 ssh-rsa
+#zark.oob.openstreetmap.org,zark.oob,10.0.1.8 ssh-dss
+eustace.oob.openstreetmap.org,eustace.oob,10.0.1.9 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9wLWa3gAdXL/oUw67cLoHKiIOd959u++OOjXLR2OcyDkSLNTQgYkawEOcNgRVBcLjXh7ej9ktuTFbLWwR/Uvx7ftP5MH0Luo7Z9CvrQjw9Eu+G/CdGzvilHSeSAdCJYWemHXqKT9Qo9zJt2BI7wRfkFKdA5uXezwMYQtiQRHMkw==
+eustace.oob.openstreetmap.org,eustace.oob,10.0.1.9 ssh-dss AAAAB3NzaC1kc3MAAACBAMaxIrNlpW+VWMGGZ2NWdXC5Dbub7WluWXVf0kNwadZcwqn60wchAUDWnOL6grGjmYNPuHLW1P7tromy/uAssMML9YiNhCbJGUMF0IDWGl7bGjoOBsdp2slRaC9oZEceXH/yaRZJbxx9dri85WFLP9hz2A9mgi6Yx2k5oc4b2jr9AAAAFQD3k+OjolSAPwhQcYB97d5DDWjiawAAAIEAo7nRfP1i3VC3ovNAvY/SlvIq6iGorlkg8kMuBdTb5HPTPR8kOdplHGQ2+8es5H8a43GZorXbaUjsrzlQ98OzHrlw3BEzFvFZgY0kJwD64aeHOsDhltHzWV0tLz0Al5lR2ZpAE7V7Wv3x3wg3a+d9pmGkkgSwAqVQAsbPTp3wma4AAACBAJnhfhHZWrgNNnagbn+cuPpIC8vSwp/GNKK6VoQm7jq1u4t4eXPqHDuNA18pE1ngqPgZk1DYQUp98G1zKlhVJrUYHqi6wNG/qBMN8NuOyDeJ3a0iO6XIccEHvS15xzy4hpRerrg6yFeIhwZc1MbsEZqnPQzB2nJKtf5BqaeOjmcN
+eddie.oob.openstreetmap.org,eddie.oob,10.0.1.10 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+CNWzEucmDqWDAP2yq5gNGq1yC/1h5KohNb2sxOkac5RSij6/6UumO8tiW6PVY6wmiI01L+6UyRIfxWzqD/p+Pm60fNGJATrUsED/EEEbxKppWqbr5RjQfmfRqu/Msv0/QR1XnCEiEH2ixiubBBN8091Jn4m/GpZkLkcizpwOE3w3/FtUhydhdHgRKxQN8Mvu/pu9/6DocI7dNWEKWVUG8gbktUHe4+gHW9RQTPe1XISECt93i1NR3DKD2ldbtZbVeo9H0oRw1v9hmQdKXz6MUBQDenr1f1nzVmMqoLXJkdO2xBh2H9a6QME63nT+eO48BT/fo3VHomqFrR0MceGJ
+eddie.oob.openstreetmap.org,eddie.oob,10.0.1.10 ssh-dss AAAAB3NzaC1kc3MAAACBAIPneLfNaMa1qPVwRTKArXULa3ZRkKxia22DdT6ajV3HB9c0vjbMsI08vjjx9nWk2YWsZVuxx2kXi92o7uPJabFrstETbOv0TGTj6VVWThgGAqa5k7orMiSPOvyLPP3E9BOdf8nRpSPIq3cs/cBi4Oz0sPvbfljomXhgt1yC6EoRAAAAFQDqrUdtdgM33cYRUGqZ4MmZuyrHawAAAIATBEq5xAT0fH0hUJ47EBV9LRyi4kJfMyBlNwrSthUdIXhnhUTsO0se35I/1NOQhTcyI4fD+ZjR8qyy5SaR/QHFar1RKUksVa1S5JH+EaLHMSEEcdZCa7chx4Rg3UMJIHEE9zoPXn7VrbiAVtHck8IY/yIrSQpznIwuZGGonregnwAAAIBVv82Vkry8ypz8o/na00b03+n2KWRrkkWqKZvXSN43zVV6GQuwpgZpDjA6bLJjAkX27H2+jYB9QO3h/r0NndV7jkSPfHlCYgOg1HICI221Bnj2r466Fz0UdKI/wQqkJovJzNjrvwfESUqPfeTGGGo8AbyLlTI/JEUrHADmshS6LA==
+draco.oob.openstreetmap.org,draco.oob,10.0.1.11 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgHj1uavQKI1MXJaspRJasiPvhrM+EB+p47PuFh/BgFK4P5DnirS5sfApEheuGY7vcIiBnG2kcpNLiFmVylYXG1DbvBXsN0zLyJiyegdbT/SFjMq6AXyBfqFOA5na977JmJNBwzG7Z7jjeo4ZowRMSyQ3DjmGdj6vmSyT/BYO4E5Z
+sarel.oob.openstreetmap.org,sarel.oob,10.0.1.12 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCohCtONR/6e/RvHnLlSbvl0GqY+EJeTn+Sxu2PyWsw+W1OAfa2jmb2DQg7S54CwbkyI/owJdVrM8Gj3s5CVOi1kIddu7+pbkqrIZKo4Mf+jviFypyZoGYHnPSBwEfgAWKtfBepnbW2RIZ9+JEXLjUyOFwU6jT8QnQMKJc5FiDP3Q==
+sarel.oob.openstreetmap.org,sarel.oob,10.0.1.12 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgQCXV76oba/hqR50+HL1YjMeMPjBj8DfyNPcuEJwSO+TFbn4IW4xkxYYl3w4NuD8H6gj2Myk55Wza5BIR0oTWtuQuGiAKld+sIcMb7R2rT2KustEVuvy5GM1/NkAJ+sUa4lTTl64KPpFukFIC8Ma4hiEhXA4LnN02DZe0NdvyqkC9Q==
+noquiklos.oob.openstreetmap.org,noquiklos.oob,10.0.1.13 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDE5XeF6tG4hu9M0m+JWh4QJmL/52+cfeXbV4qfWwdJjSH9yBzYP9LiDM97gMXMUSnomAs7GO0KMwEdO9xuIZWeYFyHvs+1a73fAus8bcAbrZPuFfPfrW3JHKtWsfhUqYNJuRHLaimLIRyqgsXy3WAHf35v9kY1DmMWkf5/VTrp0w==
+noquiklos.oob.openstreetmap.org,noquiklos.oob,10.0.1.13 ssh-dss AAAAB3NzaC1kc3MAAACBAPK6Av/wAEtRnOx12117EtAhBPnodjQur0/k0pTAaGCZNnLY3E5SD7CvSqtB+LhRO/VSHXl1Obkh4mvR6oKEDE2XOWEG5Ofq3mWngT9Ejo0Rretzc1JU7L6WPZ8N/D+3kQUXpxDYzK9CcKz90k0msZUFRfGkHVE12ip9f7G/BWPRAAAAFQC5wUn4ZkWjt0z+/bUUOe298i0QvwAAAIEAz6dx6w5equWz3T8DWPM8LRGhE6ASrwR2UNpFe+sW5EBp/M+Zgg5Ztne1nIQaDSh1iKL0qzSGYxTIb/sIDKAxy6CzTjEhWRGmuDRTPQkXwD9iXcNaLChEEP6AryrI193LnLKRGKVve6gP2vH4tpn3Ve68HSKL4Ggz2L9ysKxJppEAAACABSHM7Ez/2oMaDGNRvgWc+ViB3QZOB1CTnDOkRZuhZXFMmTGXaWPzlwqPLZKg+wVOnJgBJ4BTUV6WovPGPYWadNuqhlsKjflFQyYSkyBA+4gvZ45TwbDE4HTQ1BGlXJVA3vq5HAqcxlo2CAj4HCQJgVHzd7sfH+WwyruGDu58ThU=
+errol.oob.openstreetmap.org,errol.oob,10.0.1.14 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA1riMj4gWqiovniYhlFNUxMm/AGmV/C2GjcMP+NcJ1ZyP4OdytGeGfhUm5GwVwraimkFQQlfEDcUWY7OX4EG115E8i15cUt6s6Ya2E6AXydigvBbrdp8MNnPOWBifVN3/5Cgi8nrAebmPs88ZZx2KM/Df5qIB2rHYpuHYyl+MpqE=
+errol.oob.openstreetmap.org,errol.oob,10.0.1.14 ssh-dss AAAAB3NzaC1kc3MAAACBAKcnhyMz3C4sku0e1/nFailjoPcMwLazXq4H/kUsdlt+f2By73F5KdUWffxoeRNL0UVT7+VCKG6IXmXGkKVfvpTipFjkP1N+b7I4SuJcQ/EUNPTCGAfC3l691K8jUBD6WSlQUqZtKGnpDS1zI/ZIYiNqrQnWu2RTYnP3QvY7JigDAAAAFQDI6aaH6mWx7vTVS9m3tyXQ4GQ08wAAAIAQjAM+q8Hfp1h45UjTeD2jIA74asQl0M+4q+4EcnNPnKXRbEBIg4rCWkHdd06uhayXZ91KzCDcj1b2LSb2zOE4U1MDEpdVnz22PuEl/f6/epKmLOqHoOGu9/9Lud6OoZQSveEPYmcpEEpt1RCN9ZvkVtFdLwtQ8+CSSGXg8yfCxgAAAIEAjQztmG1LN/e7pNRY0MtV148rJY3mR2knJegg0yBOEWHUGtKY91lgboWie1YTGR3RiXckJFFYkOGWAxqEVM//+rW0hatCxEp/mWEt/GWKPpV52fc4BUhJbi9hb8sg+dAvfoHwUL3CzHzqapaRNxxbfest8dfvascAjRDFP7yxU9w=
+yevaud.oob.openstreetmap.org,yevaud.oob,10.0.1.15 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAuWeUQd5ssUd5VFyTMXgC+U6c7s63mtuEj+cL6x8EU8PqNS12RGwLpeAI5VL8UzM0YLyPjPh/yzdQN2tl9ufK7KZF0apvoSZgp/uwyG+CgdFSf66nTrZN4NA/QP1ikH3kbqcM87LfNjCrMXnqMBJ/OCqz2z+An8t0KGDXS8haxlU=
+yevaud.oob.openstreetmap.org,yevaud.oob,10.0.1.15 ssh-dss AAAAB3NzaC1kc3MAAACBAL6RC7IMuQEtD4JIRmBJEownC0a7ZEvfCTw20PV5MjWb6twZlGBK3IA/0yV0oJ+75W6VWizn3cWSBS3y1zD8KktF4fh4+FVyin9WTyFuwME8cYmRPV+kuOa1lF1sLJxqvZJRjKMjweLeNTKnl1mb03049SL2YoGwMOTdVgVBjEyFAAAAFQC7rQIvnfLYbQdX87DwlzfMDALOoQAAAIEAmAu2kK8atEOR1Sc6maxYKSf68MYMHoTpm2MW9q2x5ls982kfEUMJ3h641cbRgOAuCmQU3gHnt73sl5LY3K3oLijIhSQm8+l+GkrXVhdwx7ScLXf+8TJZRWiP6Q98VWM4E3L4wmiJksLbTlxdoew3lv8gGhbpk0XuSyLWIBZIKJAAAACATogkqFXhPFzOMRJAR6G8J4bOqg9Ae2cGtf4aMZ9xdm/Hm7YLSu3kn5IhawwU+DL494VF+ky69T01iY3e4m/kQhYB4emlqsRHzVscblVH+GL6sVEkct0HMzfqzEFcfYWqqMdig9EwTzHwJzkAb4WqZdGnWG3Ln88x3liyDZTpGco=
+clifford.oob.openstreetmap.org,clifford.oob,10.0.1.17 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCsCrNQ+QQg2UUGhBpgjlLAF4gI48VDGmcF9prulYDxduyGJIrqhOjQtKLjNksMr8TEblmJsI4JzPf1lY1rVL3Q/aZWJD5X4Q0DgEtNzfinI9JAy77JASj1osBPU2RfWSvK9C2TnEoXHxuyGKMw9iuuPLppNMjZ103PYprQeAXi1w==
+clifford.oob.openstreetmap.org,clifford.oob,10.0.1.17 ssh-dss AAAAB3NzaC1kc3MAAACBAM+YhVzoOuKt/0UrkDpWCsDgYKPvbfuvSrLeyZfssRuRP1bVsY39yfl5avZM6YwYhzuyRAbcOLYa+9ien1QTeTbV2qNogx+/yt57DWKVv7nX6WTSVfYFAvx+CMy+L6O8N6VnKXJaCcbQxOFx74c0ysXorNYU0c8++KyNfMmVVjJ1AAAAFQDoCl23tnp1pcVbUFAAxAEUb77aAwAAAIAOpGMpxWPrd1y+IxLLLCohRMCv7JlUy324PMMwNx2/u2fF3oh4kL/EUarD4/6iU1n5PJo441bLuOj5Mb58/O8qdWYwBjbUoj1CiA7qF3TXWGmPX84AlwwLE12TIH1sTRlZTdrD6+js1KUUMSzMz8tEi4tJs+bXYf++ng12sqP48AAAAIBvm/z7yPKGdLPP9i9LzWShLJKrbY9zx0BOsIzzeVJjShdyB4+NZdxQR1jjDcqJ+r0DXtanmhS5DLOS6zGYfnzzsCNTxHM/Ne0wF4goc4LQGKg2aClmyx8ZvqwF96d8nQcUIbLUydbE32xmh0bIbzVchLKEm5PuNYf/aU4snCyDGQ==
+grindtooth.oob.openstreetmap.org,grindtooth.oob,10.0.1.19 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgDwRqYuKXX3gENA5JHkVTBEL5MxC0N5Re0uX/hAVTv7AurDlJyaN34ZdK+k89XjQBPNMn7DhwA/+ddXCWg0Bb4KEngfKys9oMhZcwEWCD8LFWJcKugATfFHJPtduJrMx5dNEfQtpA0od7Ep6XamGcJ/Hwxa5iQRlD+8Kr419qNTY
+pummelzacken.oob.openstreetmap.org,pummelzacken.oob,10.0.1.20 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEhjC0AfmTSwq1TgcwvSUZgzGJp6fP1DXkYfgREfgX6MQX0uRBTLgWKM1Nz2tYb14mjycJLdCjSBCzuHQg10ufX3+5nzR+xKIy7cgwqkl6I5/jX7BZNK6t8XZfdmwnhAhLqYfG5FA49eyaVNdArgHu1fv7xczKjRAMOlKhh083038bCD8BYmBoKwj2J6D6fp6wHOD2UU4rvTP2nCEYsvTd6s3/yvTOB2bFhz2qaqOhdNI1w+dvcZLPUYO5hdndw1LGC6v56IbmMquxcieWuOtU+fbTMnI9teNo4CLPVEzb3kmwhl4LyJEA1Sx65Bz7Ve4wfgUInPoBfiX1gdSjAqH9
+pummelzacken.oob.openstreetmap.org,pummelzacken.oob,10.0.1.20 ssh-dss AAAAB3NzaC1kc3MAAACBAN3kGdbPfrsSjQuX+9kk/an83YUlJ+Yd4V+AYbRrMRYBJEIQQOYxFOFwMOdmGRIFyLj2ZXKuYY3/5UFXHFeWZxqY6kWJ0JybFfOJaZu3Iwgh8gLlBnfkRWAD8WbzvXYTCwg8yrM335tj550AqrQ/6R09l0jveeK4EyA2w8Afdle9AAAAFQCOclxhmRDMVD8adpeBrpXJ0q1SvwAAAIEAt+0ZFeCMnteeadmiCrVbHpMot2FRcem87KouLdNgdOxOpuizMJgSSHEXBA6IwvRAzrLInpm/DoCdW+bdnrJkq8qs4gEhM6Dg3tDAiUz419S/sV/uZZb9O1aN/MBEzfysO+hnxemQvmQiA1vymhWov5dNl78UwFzETUj9xwW4kaUAAACBAIgjeLkkakNDkSRAYYh0X5hGjExvYRerNWdZ6hQsGKGlf3Ud0sUkKrtzpYUvWFQLnqniQXs9q0hTTxa4rVWHiCU5+R6gBOk5VgoVyM+evuOKFT5a7TorE5STDII+PQFSHQ2dJR2QsVaKmNbcSxQC+k3ttC8vBEAmIOl28m+QZ9kA
+grisu.oob.openstreetmap.org,grisu.oob,10.0.33.20 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDTEivJ/aHG2g7TVGEXJUDcOrbQKMOwYEzWiKvMTsftxOKqMW2uKzCZDkW3BNXIBiAXoswaqK0qkh519i56tY9ff7XjH5YoYbPyWwbhMPoBlIc6wBF+uMV3dBRrb7iRe0HFhpl/XsTo5vw8x+5T/ITrlvI8T7ZfE6uTLxKFDxYOiQ==
+grisu.oob.openstreetmap.org,grisu.oob,10.0.33.20 ssh-dss AAAAB3NzaC1kc3MAAACBAIrAKvS58z4zmaRWwebJxgUUiy/P2+AWODjz2FcqspmkXXnSkXD/tz3djsp/PwgPUPt/y1J+H2dfDY0qnTtY4SM1DJi0848/BG/C1P0zb/3mdtJO2FdMVVcwITCX0XZg7ikFf4zZ9CJRiuAbiS6CKCIXcvxHhBx0O4EEaK5/PwLxAAAAFQC6Rg2wsfl3aKpecSD0ed9Ysekx8wAAAIAo1yE6yLCH6+4NEA2+2mz3XWXdf/nzOWzFd1XqZIqg3Jj8MzaNS1GLbm3FlVwl7qlXr60flsXggYkZxwXyLKMH9fhFnyrTZOJMKmLKmeqcDTZqItW7hwsaKvM1vd+ZysmOVkFiXKJuD+25AyTmbFpNUvBdIHYiL1jQaIxLEWnN+wAAAIAuF7tHFgLgrZ84nc3Yb003llMmiwwaSUjF2t9y81t+FJ4fOwhFO7lIapijrsm17v5OBSOgAONfgzNS39U+VlX61PwDmIobe8+Q8zGOv/9tkK79YwNsG/dXhQ3e7gZH4wcyNgO1BufEuAOYMxE454rbv6fdrhvsUlRgEvF+teJqrQ==
+spike-04.oob.openstreetmap.org,spike-04.oob,10.0.33.21 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgQCIrf3Ca5+Cyk7/QYU2krboxC/qhHwjvtzBpcAtVya4YPpkiQa4G5KrJQ8oxvLL7j1atgYs+GnErkeUp89SLLMJ1spbjMMubA//Mr56Bp/V/ZCr7uk6c67vA+P+EIb9QhqJt6eay4fFZ75dccw76GnDunD6ADf1VTzawYykyIrm8Q==
+spike-05.oob.openstreetmap.org,spike-05.oob,10.0.33.22 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgEvdV6XL4KV/RCLZFhyM6sSGOWOia22L2Ddc28mS8MdZTr8b/iYJpFUCmGREovFxNI5MXzPhDKTomiW6UKmoxhQcsS31Y70BdsMA+XcNqwktFUkFfXMaat43gJ8gL5lVDI3AomjxIfGoouFEhIzTrj0JYMNf/q02YJm7fPvAZtuv
+katla.oob.openstreetmap.org,katla.oob,10.0.33.40 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgwCIJ+bSxbMsr6wurBXYkeqoznHnJT4zrN7nHtajgs5CJLIiWO+Eq/Lp+egz6Irxwk3v+kbfKW9RUum5fOMfkWFwaQxP41Cz5RbMmu5Jsm4MQKr4PPVxbLbPk75OeVgo+nfkzBupsBuYGMp/GCpjTJ8rusPmYxzWBek4amKL5udfA9Ld
+katla.oob.openstreetmap.org,katla.oob,10.0.33.40 ssh-dss AAAAB3NzaC1kc3MAAACBAP4oHi33lAVyP8zjoRZe6kxcZGJi1JOgF1vpZqEsxA97yCaLGVjc2cdxi16namqdJ/DgQaRpGRM+chP6AgGN9FD8Z6Wfskm+2sghPpcGRUkr7u6mM7WlJ0xQehD4LDcxFEpZKxtalf6TlxXn9cO0VaL9NNVrpU34c2Pqxl7wg/QnAAAAFQCB10EQxYDOnsxN2xrSHEbmgA3K0wAAAIAWN0b4KREM6Uc6FVkRtOjkiAR8FWmCg8nNQaqlKIPlM4hsrIcPC5yZfc7BzamQSy4PpHNGZG64CkYr8tn8LGWouHVKKbeFOWEXIBsRBSf1NNaYI7cS7WPnGVOmkt6yHvWwPlDcVO8FpPUL9pA7kf6iCuQNdD/MyOBHdbVoU9LcNAAAAIEAsXBb+3EZhsRAYL9Jm22PsrsW2o/hO7aomMeEXvVGG8Wuy77lqmcIvlyW3zhHBs7ubI9TZz1XDsgLK9giCkmqCyKmUsTXGsu9e4veOq+sgvXdbhoBMVi90IFsPLPUdPN5mfovBDHkwi60VtDwOLAX368pFfBfSA50CZWfhwUu26E=
+thorn-04.oob.openstreetmap.org,thorn-04.oob,10.0.33.41 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgH5H4Ra0f4+LfMyJbVpoJIN9wPrC0bbNEJUVIOmtPpxRE4HvoqDOBE8XfHIunhNeTxK5Yzfinz+fCq2XCv/8Sgrr1qJBUQwi9kHfRBNmRJyoylxY0b33Dpsk5kxcAl06+sSugl/OcbXAyW4H3d+dQAUMlRPEVzQCgd98gGrTFF6p
+thorn-05.oob.openstreetmap.org,thorn-05.oob,10.0.33.42 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgQCYjNImXo+2xnRT7T/JiHh+eNl8I5i/sjB4KBaHizKuJnwH4heLbPtmbI9ze9MV0IHJp/289kwT3bSgj0nY9zi9Ucdry0WtPgGQO4JbDZXzCBhwa6MhZVLAIOKU34fK6AIuZqzQJwXeJZuCIiwaoliUwY+QwNcX3rQho80eaK6XFg==
+orm.oob.openstreetmap.org,orm.oob,10.0.49.3 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAn68BVVd15SyHq1vdXYZukNkoxBPlNBgA8gcaXjlQg917A8gXcHaJQ04xSwt/jkbbvELNuvYDuw0EZAqQQHG1vYsXffg8bYrEq/WUs2+oc1O6iiR3xrzgDWAdefEVk+Fk8TXRGI3dy6IBpFoQ6ywvNCbFvVcB41FLRtBGOWdJFZM=
+ouroboros.oob.openstreetmap.org,ouroboros.oob,10.0.49.4 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC0b16+oF2QHYj+iIS2YT5VnH8KfdYckm1ujYSo5WitGONMqhN872W6krqYbW7GjFvrJ2d7GbNaY/3VeVURLumgWBnit77bExpga++/QYsE90DSoiQMeUT0Q4QuPWXcTIzAcGesda4VtQkTRBTt1UlmdEGBP3eDAqL2GoW4DBPCiQ==
+ramoth.oob.openstreetmap.org,ramoth.oob,10.0.49.5 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgnWJq8z9xvNFujhE0P040rCO1yEsH8pnQmGOGehIRcfclQBd2wOO22+8kpy04BMT9FaFdxjgNTUWtfCwT+oBsxbHIreahld34vFVCw/VSCiPEuUhBdZ+fN9hdLGygrnKxA1b2cIs532nm4LLDoP2VpM4RZuh6da+LV3eHnfDlZHO870=
+ramoth.oob.openstreetmap.org,ramoth.oob,10.0.49.5 ssh-dss AAAAB3NzaC1kc3MAAACBAMjYCKyJfA9/EQWTxwqqGBq88dAaWWG0j+ggoGEYuIWqcdA1NeF70BIiRGvAV5/oBy+p/snd0LAxDG6KnWglOo/0cjzcfys/RQl9kTa6gkcFPp9lUqRnuDF+y/egZVTU3KF376k930nNdODMe5PxECnZdC51158Zga9Hwj0+5nalAAAAFQDnh0Gx+gt+6Qc1r74FeNCiIPmzIQAAAIEAs81g5c2sF42ATY/gd5ustNXm82xfIAuRGeMCgxyXBvFM5UXuLnfOx8JVB8wu9eoSmxhDiuVX7ija5FaKAAucPBXWh/YImH+T3SOWLsxfDh8XglH4NvEtj1r+90VWbX/f1Qy7IsmmBolUCr32qD5cdeQ3JPxvUvO/TdSHaIgGK30AAACAZiVJOiM9mfMf05rAg9fjo+NKxL/jsbZ8ptTnNOFBNjq0XydXQF3Rnt01b/cUSv94VmuJgv9hq9L39nk/dSnBVQbKwIYyB0/NR2Fg0sYHpo4qj+7MFndv+ct9pVd+l9pmlEoR8soLeO1hSVeSmj9YvDzc74lx8FYMVE6+yed8ltw=
+spike-01.oob.openstreetmap.org,spike-01.oob,10.0.49.6 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDHhi90mKvMe+FL1pdzBPWUfC+a0ckv31Qou7Yby1Kn9xhrR5oHvyoT4bc/xPrYvaxRZUHWn+J66ZdylhyfCZf6/5g8xghJoYVAZJn9yCV0R7xw2fzHCgue3iS/Yrep2V3DRaXt/zy+PCe7wZX7InLLtp1rV/Vx2xG3lV91OGa4Zw==
+spike-01.oob.openstreetmap.org,spike-01.oob,10.0.49.6 ssh-dss AAAAB3NzaC1kc3MAAACBAOE5d8RsNmFZxWkcwXHisg5NowzVyvYjW/cXmDRkeN9r2gvjDRj+WU8CIo4rhVhbJIepEA/BUkzEyDBrBOydFa/pFH9KN+tRnSabRHaVweXr337KX9ltSGoPijSwUlDhVITMMSZ5v50tJ9bokyZEYbgpbzPo+slqgMFbR3fr1MvbAAAAFQDWzbv+xMTMOYcQQ92MCaQKtsXCJwAAAIBW02qjzbss0X9TACVhGHGbAy5DcfybmY8JZhfUgqR0xI5rCufUW5+dY7EQu3FlE8bC/R1rPrks7wngmut6xPMtkpcpMYFoxFPgP8/xfwkTNYMs2J5Vbrb6k6e1XMKt9AID+QzhEjTVxmwLKAT8uZGDZjY8ujYnQMbM3wPbCbv/MgAAAIB4xUK2Of6YBWBOpW/0GPfFH/of8Txv2ErpVmTSTOFaO7KD6x4jcKjn9nFMvVUhW/c52UYYcscE6uArd3XNbJBw/H58i26V8RooTkQVWhKNbp9ktXPh8yADNzVq/rRW6kvNYHZbbTev7WZ0NPvz2aIrTLKPcEcUwLq4wpNBe//1LA==
+spike-02.oob.openstreetmap.org,spike-02.oob,10.0.49.7 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDJfkctRhGPVyPY18EVcegsABPTC7PsCA6Pt2UOkkzANJKkwrOUJyn5GqgJYHkOb3hWqPlS89zdlV9kXlvTdUZ8QKw4xys/5H5+CWwbag0h1EpDR9S0xO9gIgX5DgyB5Y7oNS8o9AolF+hgyUdmBYO3ff+h7eu1PnqBn8TfquqVcw==
+spike-02.oob.openstreetmap.org,spike-02.oob,10.0.49.7 ssh-dss AAAAB3NzaC1kc3MAAACBAMxbg3AjYJcMX0jlgyXslqLbi3MV1zAVunNGqFOipJCW3thZ/D780MbQiXuXglqJQxWsELy+8RVVjt6/rcnZHORsH2H8M0/3WdlEUW0FxMUISXUAVtto0Fk1v4QznUtyxoKIg7sXktmreaNEcLBA7Le1bOBf/Oz14uQbmI4nycelAAAAFQDEMSn6sAPKhEYhYJiFYsDoV0aWfwAAAIAG9y+c73QbYqHBOdNISG22W0BYAnUj1L90lW44xNnmrVOc+CdTKG3VnAQcIc5BeB75sfE29JOmUGfR3/clCgCL54V8D+gEH3omtSG3eG7B+OoWhcUIoIfgO/3w2ZactdU8lA2qwSfZ0p7xLPsrDN4wuORPYFpoOU/vV9hG+dh7VQAAAIEAuk45eD65i9Gx6hHQuCoN5EGQHhL5qvO2gbShYLNqEhkDN+TmdTLK4Wbevy6tOdCrCRKP5zhoycbqm448hINFtwBPXGfRfhDsAGm075pMwljlh/LU3lSXbSU1RkmiXqjYqcjl0ntxkv2qA+zN7G1/oJK85pwScyiMo9kOuwyh3+M=
+spike-03.oob.openstreetmap.org,spike-03.oob,10.0.49.8 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCvTY6CDpJgBcU5T0l7Hmn6UkLZw1d0EQEPlcQM1UvLfdSKayVR79Yl31eVWFbA+R+QqQ8LKcmzx6ztWPuemW3Ym/gZ7NNYH10y1Rw9LywWhVnFOjKIBUVJmjdiuxftyCPveHu672k1KJ+bApXlA3/oMBmtCckr2Wod2qJDx7JIeQ==
+spike-03.oob.openstreetmap.org,spike-03.oob,10.0.49.8 ssh-dss AAAAB3NzaC1kc3MAAACBAKHL6HuJER/kKOFoGbPvQ0ghCw5lJ4ACsZHi4ptTwpBh1rx+/mmktTU6/U+cP8ocGo2XIuoCaBMfNK/eqrh37a8/fZah5+wxwJBWnZqncOhJT9EjRfvRtbJr8GRtCukNxX554zsQBSqCn9CIP6E62EqbYUf0qfROX5o3SZVu2WzFAAAAFQCWHnuBktRY7R5n2ZuCL1Cdx5hevQAAAIARZiVCIAKIJerBY4AnGADzRf/m21PkhksRIKcqge8vDI5z8MMgYkmtcrlqgGPEavnajBPlAF8DdDFRbx/4k8K5ZZdr+4ipp2++V7fbkg6n2MMwR7qTN3FpoNtLwXSHLlsueAArRW3RNlYdtx9wZppUq+cGlqr0J8jXS4UOLH3MdwAAAIA3Y4EPZv6PufNBppuegYI/gziypGwlNc//XODoIagXyDclGxGnqh36J+AUWxuILQeHRTZzdLCVazFZt+EGJeKI7/C3yJOkSp3vNnre4VYmGGRp1hcBKWDVCltjv+phRMXGiuGSQdqCy+AfkGSctNQafRnQuaL5hLBytHxbXIADhA==
+dulcy.oob.openstreetmap.org,dulcy.oob,10.0.49.9 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgmlwXGPIPDqoMz4s5edr+G4iuBnCYcFXjY7Et9jG/ezI6aIKd9lEOXvnHJX5hrC21aqd06dhyMLwZN+eSjJhXNaLtYmm5P442H2ZnGca1KNSpF7yRVhn0eRpX39xWK3biVfMw64mzvV3636C1adCkgBwuaqCvz1EHm/KRrySfuETFLU=
+dulcy.oob.openstreetmap.org,dulcy.oob,10.0.49.9 ssh-dss AAAAB3NzaC1kc3MAAACBANcuNreghg/8rJAmfsdD3Rp58vN84Ee1oEFMgGSxF6+yEVTbXrjQoH632jiBXSayQLXGEzrVTsGaWgujK9xT7OinNa52ydnJ/WZp5qK5FdW95h5m7pnUE3Jmm2cPmYpEJW62OeMStmTGkK0EvN2wwRLuts9R1NK63tWjFWik7QmrAAAAFQDNtW3WKlCugOFZnjIh3fBuDakdlwAAAIAzy/pxXiix8yKhlb0LQJ1izilnn2IXRvAHv4aM6LAiq6QIDj2XyT9oTS/77BguCw39WhVG599eOSRckWXFgUT2p3pWBBuuDbLEhQqIc0KgufYh/ygUdjf7zs0O2jusFkLMPgF/0IgRs/ftb36ERn3KJ4C1P0v1ABk9t55Qs985WAAAAIBZFS2HS1ewjv+/jAdUH68zT0mNBctnrqM8ixqT1Xd2Tl7SKjl6Sz9yer+6+Gq7O50U0FBS0pQPo3f9msazQU6BFYCzuSFRIJQmH7uKGPHHA7mbuow6sEOhtXBzq1VfI4addXyWlYLKXxv94/gt9xlxLZHqU4ZZb3GPGbU7kKJA9g==
+ironbelly.oob.openstreetmap.org,ironbelly.oob,10.0.49.10 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgwDkRqR1VRgHOON8M7YCNnIG8k0zukAN/r4L5fPKTvWmdhe17UnxywPc+TySjXqNsXQ/jPLGvpO5uoSG3dgT2N7NUdAtdL4Enb87dX7yTbJTJzMMxTb9HSI1SL2/5iSefyAVVo1+R8DMmFqTWa2eFHoD9IoxFSNSTarTZQgmH1oZYoZX
+ironbelly.oob.openstreetmap.org,ironbelly.oob,10.0.49.10 ssh-dss AAAAB3NzaC1kc3MAAACBAJKKtKZBECA+wtvYtrEeMyTzkm3X/4IfC6E8NcnZouMCHYn3F964+pG7mRskZAi7P95VwJYx6TLkiK/MNKIh8mk8M4Xxu2USIXblkTPraPYHyVgTkfZit6F9qTR8cAOlHtoY+9GgKmWMLC+xeOgPtoERvUyuuprXsAztZ9C2BKWjAAAAFQDnPXN3n2g1xxsYZsaQpdPuijb1tQAAAIA7/IpFy3mSgpu/TmmBuYLccdRTCNt493U3wMLb/JdUBu4h1FM6J5DSozcQ70ATglpLLYa3Ru5ztv87Esu8c7CH/TAH+GZ5/3LJtS//HJDt+53yy4CgwO8pcKbYo0rfRy4/QdFXWeBUtM2XN4hHvbaBJ0fzP1gXI1GHvz3OQxWICgAAAIAvZVlk6GX+uGpqLdW4F1ctkuqUnkIGzRziJ9Gk46vOOFCPxU8bUXLGzvC7Zv3SOR04YH7/LDMUof2y68EOCbH9YT8mHNqLdZ9TxOWv8wUaDX5O9J8JXngLwl+U+ONitseg/PrEZKmP2/cR42pFwuTzb59+NSkEVAa0ZK6+2FkWog==
+spike-06.oob.openstreetmap.org,spike-06.oob,10.0.49.11 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDwQVb/cYgKp21vw6+jKr5TLAD77oKunbFbjvwPL34iLRDqdJcEOdJBV1A63ZDUWSWjDUrTa0kyneoiYdD876EpuspZ4bPgmiHBvug5NR3usxa8PAsia1K+fONAGi3+s96H6Us273KHNH5QwyBNDyYaDDjIECkydU4bQT0FSX0j32eAHI62ZO/H82fUyL20PIK/nCUaJUd+5iXgcTfjP+eL66ghgPCgXGF99/w2+3EUxP2IN9J2yI57H/rYn3rj+NdZyQuzc0TAToT341cYh2+a8R1Sb/DEFiMZFE2hJ2NeVEaBYxPSlFfhRtlB6ArXg5QL7e7UScQh/ZHLU26A1ZaB
+spike-06.oob.openstreetmap.org,spike-06.oob,10.0.49.11 ssh-dss AAAAB3NzaC1kc3MAAACBAKwUXFxncoW/AmYePSswZkqbHJDN5zI6MblYRtyLwSzfdthD8KCiDnoG+6opsy18jaX+sX0PTz8hfNVUPCMhtiTSgbGqZuQbriT1z8x3yRbGShqH1ZGC2Tt8x8k7ft17Z1tgnsnmueMrGekks6/kMZWYl+zrHXbrKCM4uPIHjK7DAAAAFQCOmXTNMg+q+8BybEEHDtWH0hbnXQAAAIBhZi+1jUaHu0UEtKnPRnChDyPrWXpgwVOM+goAZCOxfObI6PcxrIhB31gRPWNETR0UzMb2K9t1oCNdyyq7Y2TdFHEVHOTaBTWS5C9Bvtz8CHSou8mibH9sIhK2H8FevdQPOZHeUxQRSx+JzCL+f3qMovs05xVBNhUHO5XLtzIKdgAAAIAGlmX7cp+zx8D2vPiZEcczjJIgK2DvAu7t3ZAemcX5utUNKh0By7xxT8DqzIPYRvoAI+//4xqt11jIdO7KADc28uyv6oBAbB8DwhlbRONM9O84tqBTIxu0bQXtsYpkTAQvLlrDXMYDx5aYLpP1haTbGgdtjbDCz4FH1Qi7cBN0kw==
+spike-07.oob.openstreetmap.org,spike-07.oob,10.0.49.12 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCxLxAbMPZw+LgzB8JmTLLxqc6CZXYA3Wo18RM02+EnmtRX6AAf/VFb7E/VpgHfZecwnFK7u21R47+fFdHCb8EDYGeWbOYoEOYMoDh26H8/aFPHbldgG0xs9EwfTryWB7iZ2sD9nLv+nBpDkFXVq53kscmDlUKQrvUyj/zR55xGxcq0ruu3w05ZeGx5I6HRY0xeK+6H4s6sZtF24Zm3CttQ5M7ADgWffE35ZwA9tEdioM3J3c5EcV4HMdhl7wame6pID9+FpDEtcts5z5sfW9Y0yx3FHrXCxRWxHRbyFG9/+4RNwKJBRZrdb+VSLlrYVUFLEfb1AhOxr8ZfSsJU1V0V
+spike-07.oob.openstreetmap.org,spike-07.oob,10.0.49.12 ssh-dss AAAAB3NzaC1kc3MAAACBAKzH4llCRo3t5ifkL9qB1KoWcAw1ROGVAJBwE0GkFZRQvzGQ7CE4anpFdv8BVlUbFx9N6batsC00ERDL9ReWQXWMa1oHr9AJ5Prpgt+azn3AFrKhhkMQZegjnZ0Ddsl/XSmFbRbJX5cnvrSIBL5nEC6kBCVFDiuH8MlsWaUsvUtbAAAAFQCWQKlZ5osk9BZKsnss/W+Mv653RwAAAIEAmbM4n4Sl77tGuTQZrlojpjEF/qm4iUpnAwbE93e2EIr2thnM+6QYtzYZ6VXSXwrh4UW6d9lL2mgSxQnY1HiM37y6e/oNFrsluK5j7AhxAYm4bHT+UpqyU/zl3eUlTdvBxhkTjQTT+wTsBgTwu5zZaJrlEPzoYkCQNJRS5AAw0gAAAACATzzX9K2AYRf7h8gK90abOmp/LYNO9ghhbhifsIrIxfShsFubUSfRO+m9e9wG2/1kwQY2VuVpdM86wwFvjHFlo2VHQkIl1JkP8pmVKs/QKSo4WSDY7aO8bpQK2Xx7QC06PUnllgXsPcyted8BGCoTLMVRkmukMwWls+Qw4fr7z18=
+spike-08.oob.openstreetmap.org,spike-08.oob,10.0.49.13 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCm7BnJ/+IKh/uAI3vIjIlkqq83jFkuxfxPuMty9/jhm9XoVbf+nqTfRQ1zMZn+bqjEjLRFTU3uwsjI61fk1Uxru34JKoJM3axNPK0S0TH6Gh08oLoBCCOti1/tTAiYaSLFfauucnJeEMkKsmIaM4LzawphkIuWu5kUv0LteuycqJAXZKr4jAIYZuxQZ2e3ofdzQoXIjXbEg/9EWyMA+zbUYlAZpELicTOQywhpez+TpZ8GUnMuya7jv5pTWfiTbSkToF0HTrKUxIEg1HYruBs+0OYI+LbABe93z/fAk3j31y3FAPEnR7vqbM7mc4DLSwgtKsKkpGGGeVHLEJtHVhhD
+spike-08.oob.openstreetmap.org,spike-08.oob,10.0.49.13 ssh-dss AAAAB3NzaC1kc3MAAACBAKJKB5ukyM8DRC6fbpXb3KEqSq4CmBqrlqXCFaktWKFerKUJWx5No/xWn6n0H46FwpznH07Dt/Mom6XuN2A0i/ZD1pE0VHnQif23+L3PBu7t3cDPVJkj+eYVB2avPPrwLGhOLOss0oKnBwhOgK3FTerCRUN5MuczzPY8xtz7w495AAAAFQCj87X4s3sLxHybJmuRFEuc68Zd8wAAAIEAhajd+H+3uVBAIKdWpn6GoU6bP0y9/ERnz1GKp+fBlTVHT+eSc1E567HqVErHxc7QSFIBmdlF88MyS0izQSAFKdzevJWqUbDeUKtcB26hGGrvHOp1dLsoALpuUDhOZvKIzehp5linYJmgnN91piZ3BlyxT1acr4zdceIGNL7rJtwAAACAYlD2EQvr2JI99MooGimqEYP/zC/HhChmtCEIJ/XQrOuKxBL4AlegFNECXBMn4JHFbdyb59LYvVlykuCgLgNY2EKObgltKJ5WLmzIRpUTBW2TlwAQiRnGqA6TGUpTTlKZFqAnRSqOJfcvQw9E4HwlN5TeOT5kxN9j1duUaV5WLx0=
+tabaluga.oob.openstreetmap.org,tabaluga.oob,10.0.49.14 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChE4Wu5bUAgtJxrappT9kZeftw9gdj+D0QmisCGHbLsDxDnww7g5gplexQOf5aEtLon5NU4HNixcEFZ+/RtEtTuVaC7wAdNF1HOdOecexvHcEFlR6KPrdAKykTyo4hWYUd4Uz38zp160V//ViAgylpvU2dhGhAWKcxgmamNMz9iPd99T0fW9bXAzpiB+yBuBskD+JyA9bQu56mfIW4u4rh1xgPBRyUdorqetM97QJ/fcdkN0m4qVda9qP0J5DUli6Cq8IbEbv87r87VPV9o/WOKGBJtclXdUuF9aLAvP3p5V+OuxqUCtvy2r6LDBvVURURb2/VXzn0O9x2pWE6uPeD
+tabaluga.oob.openstreetmap.org,tabaluga.oob,10.0.49.14 ssh-dss AAAAB3NzaC1kc3MAAACBAIQNHSK0uo1CehCFag09Hd+bJ+CDD0LPWoE/6B8Ye3woVQw8XhJPIygWyHlsFo4rbgkTnvz4ooKTUHnisEIoAA6hlqFTVP1LQQarkmba5Gf05x42hYKjM6mYvcoDMAdnkPueqKIa2CQVNCg3sopI2isxaUUWPEqrVeTMgI40ofd7AAAAFQCSNIl/McB7R/7q4fFxZ2dVGtvJGwAAAIBNRHSJrnm4IDYufJetkWyn4KEIkycUMDs1WE1H1LbtmsIaBAGaz1QJKclPCin+hCv/Rne4oPoZWGl3SqB7hjBkvKUOKRaMp4eG1YCpEvAhgNIFjPkgdekctQ1H6/+7CkQmMVelh78cUMOUYEoky7ISiaKUT3z8O9EEjPIndreNBQAAAIAQeqPxG9B+RJtcOqnW5d9M8VVUNeW10A2R2AMtTEH+/hjaoXUPpL3bQ0Fl3aWQKYJMRpOM64GgLswEhxeWf0PzSAi5CwBmyhIEUJpJ0jHOYSUXC6sLpBMV1ad4gF/63CBAgL1fUnQ/FWDtZwDEnBksDbYSS6EJB5m1o1vOx3SHWw==
+odin.oob.openstreetmap.org,odin.oob,10.0.49.15 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCeK2EVK4rbsdoTq84Cl5kLhbJk7gbaNav61yFuSKfSsizzbH/tzxmiFA7mtB39WU/BlFsTHAg1mHY7cCPE01E811CDPIQhZGEyloh5ftbTACCcGAjKBhYpwTPEteBqlIk3lpN1TNTsnJSYaQay3rbOQ+IXTb8nzKYjTgANQ6QXxSq4BfuRmvMRlNw7ZuIerhs8OL2G/pxldL6AYDPDFXBs9mvvqqS0fw8rzxkjFNUc/z9odFoChtlZVbp33/LTIBQU1dY/XTxaekErjT7H93KG9NP8mmIFZtU8oRo8553ogTYVxFr6hD5D6KkbveaFU9oBDRYlJPWtdHksF8RAEpjN
+odin.oob.openstreetmap.org,odin.oob,10.0.49.15 ssh-dss AAAAB3NzaC1kc3MAAACBAMxXgZGeLxWyQCErmy0aGppk2/xHj3GTATPCQgf/Mtm5PYK7c3x8Z/fEop/BBnY2/YDE709g28Tv+61I4SD9D33OO6ABPEapHEwqp3CIYuA8+JFJhuo6Sz9h9bca6fx/KVjdDq9wbmx5IOqEFQlBoCSGJvYw5pTptVFN+nLeiTLjAAAAFQDt76BO4R+GaDn6/SeJvP3xAuqkmwAAAIEAgbhpMfB2Gk+babYDnWTWMkFO1FObUdi8/3NmiS1XUPCzdGkL1h2psoQIMXFtrNfEzSPx320rjC17T+JD1KGzXTBsPSd49MhznMc13JK2YT6KJm3io1CLKuzje4SxrpddM1Uvs/sOLmeAbdNqlUsAM8KUedEYTo/SXeVecos6dboAAACAasbTSjiTPW3NwH1yrEV8xWFCAmsmAPvqwGjaLjrrDdNQCbJ0KHMY+lbUAmT6oZ5qcrwwc2A6B+/v9XBISiT5XWELdP56bhuDcWC78aJDdtfDK1xuMtsHX5tpQcKB7IrPI+2UYVhz7zosvcCbn8FukgDx8sEcp28rHaFB5WPCjig=
+karm.oob.openstreetmap.org,karm.oob,10.0.49.50 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgnWJq8z9xvNFujhE0P040rCO1yEsH8pnQmGOGehIRcfclQBd2wOO22+8kpy04BMT9FaFdxjgNTUWtfCwT+oBsxbHIreahld34vFVCw/VSCiPEuUhBdZ+fN9hdLGygrnKxA1b2cIs532nm4LLDoP2VpM4RZuh6da+LV3eHnfDlZHO870=
+karm.oob.openstreetmap.org,karm.oob,10.0.49.50 ssh-dss AAAAB3NzaC1kc3MAAACBAMjYCKyJfA9/EQWTxwqqGBq88dAaWWG0j+ggoGEYuIWqcdA1NeF70BIiRGvAV5/oBy+p/snd0LAxDG6KnWglOo/0cjzcfys/RQl9kTa6gkcFPp9lUqRnuDF+y/egZVTU3KF376k930nNdODMe5PxECnZdC51158Zga9Hwj0+5nalAAAAFQDnh0Gx+gt+6Qc1r74FeNCiIPmzIQAAAIEAs81g5c2sF42ATY/gd5ustNXm82xfIAuRGeMCgxyXBvFM5UXuLnfOx8JVB8wu9eoSmxhDiuVX7ija5FaKAAucPBXWh/YImH+T3SOWLsxfDh8XglH4NvEtj1r+90VWbX/f1Qy7IsmmBolUCr32qD5cdeQ3JPxvUvO/TdSHaIgGK30AAACAZiVJOiM9mfMf05rAg9fjo+NKxL/jsbZ8ptTnNOFBNjq0XydXQF3Rnt01b/cUSv94VmuJgv9hq9L39nk/dSnBVQbKwIYyB0/NR2Fg0sYHpo4qj+7MFndv+ct9pVd+l9pmlEoR8soLeO1hSVeSmj9YvDzc74lx8FYMVE6+yed8ltw=
+thorn-01.oob.openstreetmap.org,thorn-01.oob,10.0.49.51 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgQCFBaTPsbNtWlUSsGnRzObp3NVC6MOro10p4qSXB0kwAB+hQx/IrIH8BjduR+b6Uv2cm/UMnGRzS/1lGYe15cSs0V/IOUyXdVeX+jB0TXzS4hTqclGKJ0Ay2WEsgW27IdPxIjQg/W77s9AZ2UlyEtT7gK2oergD60yUvRfLLJioYA==
+thorn-02.oob.openstreetmap.org,thorn-02.oob,10.0.49.52 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgEitEET7IzW9j0lgxcgXT9JgzDR/cbQdlYSwV6rcWvHW9cz1ArWmJ6BY2AJ6CG3wTznVbHPupiFKf0jvkX0omKu8K90f5FJc2/BkUP4aG72YmAoPVe4bflGykvKJE9Rd4BDyPWGqI955Okp3VGCEKXBS/fwnoOZlei+9ex334hK2
+thorn-03.oob.openstreetmap.org,thorn-03.oob,10.0.49.53 ssh-dss AAAAB3NzaC1kc3MAAACBAKZf6qtRHGHjPfOP3drwO1m28l4fpN5X5c8ArkeKhV3aTzY404uwCsSvfYQUw/s24E+989MWZxLUO0Ib+nV+hWlK0nxI85bQPIvOjaWNtbggOfNdz4VyNcLxxzsiJqNhQpGQ3LW2zQ7fsP9pM5ALAs7MDOaSdNja58aUgEMY1ta5AAAAFQC1r9L5Mkax780fOnwkDB6eIaNjCwAAAH97vSxdyRel4IucL4Ckn7Y/zVwFeLpwHiVP41MN7dO2aApuWvsygLU/FUAouv/3PRug/bAAS56w2/JLKVvyo1aRPNHAvgPFEDodqLc+dnC1bXFu1VR69ntQYTEe6iReLlwzeEPLwTW5ucGHddXVbP2jG3R+JEmGGt87P3JxicCjAAAAgBrDGGrP1jST/axY9UTs1q0ljkET93/vIitbc/C87pe08ccQUL/PUn0GTrVhXps2Q2nfg2IuI32vYYy0lNKXD53NOpu5G0ZxEB6BYxwejwD5YLZhJQD1mtZ5JvyAPeeWfZa15ZRoI0qzg9RxzB5bp4cRKtHxFcGRAj1jjHkN+80x
similarity index 56%
rename from cookbooks/web/templates/default/statistics.cron.erb
rename to cookbooks/openssh/templates/default/sshd_config.conf.erb
index 900856cde3694bb57c2a0b6986ce26d1fde0415e..00a540a5e54e9d114d613d2a277220eb79027bd3 100644 (file)
@@ -1,2 +1,3 @@
 # DO NOT EDIT - This file is being maintained by Chef
-0 0 * * * rails /usr/local/bin/statistics
+
+Port <%= node[:openssh][:port] %>
diff --git a/cookbooks/openvpn/README.md b/cookbooks/openvpn/README.md
deleted file mode 100644 (file)
index 4936476..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# OpenVPN
-
-This cookbook installs and configures OpenVPN used for secure network
-connections between our datacentres.
diff --git a/cookbooks/openvpn/attributes/default.rb b/cookbooks/openvpn/attributes/default.rb
deleted file mode 100644 (file)
index af20e4e..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-default[:openvpn][:tunnels] = {}
-default[:openvpn][:keys] = {}
diff --git a/cookbooks/openvpn/recipes/default.rb b/cookbooks/openvpn/recipes/default.rb
deleted file mode 100644 (file)
index 2446fe9..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#
-# Cookbook:: openvpn
-# Recipe:: default
-#
-# Copyright:: 2012, OpenStreetMap Foundation
-#
-# 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
-#
-#     https://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.
-#
-
-package "openvpn"
-
-service "openvpn" do
-  action [:enable, :start]
-  supports :status => true, :restart => true, :reload => true
-  ignore_failure true
-end
-
-node[:openvpn][:tunnels].each do |name, details|
-  peer = search(:node, "fqdn:#{details[:peer][:host]}").first
-
-  if peer
-    if peer[:openvpn] && !details[:peer][:address]
-      node.default[:openvpn][:tunnels][name][:peer][:address] = peer[:openvpn][:address]
-    end
-
-    node.default[:openvpn][:tunnels][name][:peer][:networks] = peer.interfaces(:role => :internal).collect do |interface|
-      { :address => interface[:network], :netmask => interface[:netmask] }
-    end
-  else
-    node.default[:openvpn][:tunnels][name][:peer][:networks] = []
-  end
-
-  if details[:mode] == "client"
-    execute "openvpn-genkey-#{name}" do
-      command "openvpn --genkey --secret /etc/openvpn/#{name}.key"
-      user "root"
-      group "root"
-      creates "/etc/openvpn/#{name}.key"
-    end
-
-    if File.exist?("/etc/openvpn/#{name}.key")
-      node.normal[:openvpn][:keys][name] = IO.read("/etc/openvpn/#{name}.key")
-    end
-  elsif peer && peer[:openvpn]
-    file "/etc/openvpn/#{name}.key" do
-      owner "root"
-      group "root"
-      mode 0o600
-      content peer[:openvpn][:keys][name]
-    end
-  end
-
-  if node[:openvpn][:tunnels][name][:peer][:address]
-    template "/etc/openvpn/#{name}.conf" do
-      source "tunnel.conf.erb"
-      owner "root"
-      group "root"
-      mode 0o644
-      variables :name => name,
-                :address => node[:openvpn][:address],
-                :port => node[:openvpn][:tunnels][name][:port],
-                :mode => node[:openvpn][:tunnels][name][:mode],
-                :peer => node[:openvpn][:tunnels][name][:peer]
-      notifies :restart, "service[openvpn]"
-    end
-  else
-    file "/etc/openvpn/#{name}.conf" do
-      action :delete
-    end
-  end
-end
diff --git a/cookbooks/openvpn/templates/default/tunnel.conf.erb b/cookbooks/openvpn/templates/default/tunnel.conf.erb
deleted file mode 100644 (file)
index e2fcc35..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-
-# Set the local port to use
-port <%= @port %>
-
-# Use UDP
-proto udp
-
-# Use routed IP tunnels
-dev tun
-
-# Use shared secret authentication
-secret <%= @name %>.key
-
-# Run in peer-to-peer mode
-mode p2p
-<% if @mode == "client" -%>
-
-# Connect to the remote machine
-remote <%= @peer[:host] %> <%= @peer[:port] %>
-<% end -%>
-
-# Configure interface and routing
-ifconfig <%= @address %> <%= @peer[:address] %>
-<% @peer[:networks].each do |network| -%>
-route <%= network[:address] %> <%= network[:netmask] %>
-<% end -%>
-
-# Keepalive - check every 10 seconds and reset after 2 minutes
-keepalive 10 120
-
-# Use AES-128 as the cipher
-cipher AES-128-CBC
-
-# Run unprivileged
-user nobody
-group nogroup
-
-# Reuse resources on restart to avoid privilege problems
-persist-key
-persist-tun
-
-# Set log verbosity
-verb 3
index 8d4f9a3b6b10b86b3f0b0626e8a8a3112acb4b13..ef45921001270cf1c6cced4fcc22a7fe374ff0bf 100644 (file)
@@ -1,2 +1,2 @@
 # Set the default version
-default[:osmosis][:version] = "0.43.1"
+default[:osmosis][:version] = "0.47.4"
index 8de53eb37823aef3ce133c5c6eca333eae46f22e..ff38e90e0465da8d84b61c710593585bf667b6b7 100644 (file)
@@ -22,11 +22,14 @@ include_recipe "chef"
 package "unzip"
 package "default-jre"
 
-osmosis_package = "osmosis-#{node[:osmosis][:version]}.zip"
-osmosis_directory = "/opt/osmosis-#{node[:osmosis][:version]}"
+cache_dir = Chef::Config[:file_cache_path]
 
-Dir.glob("/var/cache/chef/osmosis-*.zip").each do |zip|
-  next if zip == "/var/cache/chef/#{osmosis_package}"
+osmosis_version = node[:osmosis][:version]
+osmosis_package = "osmosis-#{osmosis_version}.zip"
+osmosis_directory = "/opt/osmosis-#{osmosis_version}"
+
+Dir.glob("#{cache_dir}/osmosis-*.zip").each do |zip|
+  next if zip == "#{cache_dir}/#{osmosis_package}"
 
   file zip do
     action :delete
@@ -37,25 +40,25 @@ end
 directory osmosis_directory do
   owner "root"
   group "root"
-  mode 0o755
-end
-
-execute "/var/cache/chef/#{osmosis_package}" do
-  action :nothing
-  command "unzip -q /var/cache/chef/#{osmosis_package}"
-  cwd osmosis_directory
-  user "root"
-  group "root"
+  mode "755"
 end
 
-remote_file "/var/cache/chef/#{osmosis_package}" do
+remote_file "#{cache_dir}/#{osmosis_package}" do
   action :create_if_missing
-  source "https://bretth.dev.openstreetmap.org/osmosis-build/#{osmosis_package}"
+  source "https://github.com/openstreetmap/osmosis/releases/download/#{osmosis_version}/osmosis-#{osmosis_version}.zip"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   backup false
-  notifies :run, "execute[/var/cache/chef/#{osmosis_package}]"
+end
+
+execute "#{cache_dir}/#{osmosis_package}" do
+  action :nothing
+  command "unzip -q #{cache_dir}/#{osmosis_package}"
+  cwd osmosis_directory
+  user "root"
+  group "root"
+  subscribes :run, "remote_file[#{cache_dir}/#{osmosis_package}]"
 end
 
 link "/usr/local/bin/osmosis" do
index 610f68605dbd1ef35da701605bedc919bf63d3c5..cc3243ffc6ceef22dd0bf31c6f5b142f3e69e9fd 100644 (file)
@@ -4,3 +4,5 @@ default[:osqa][:database_name] = "osqa"
 default[:osqa][:database_user] = "osqa"
 default[:osqa][:database_password] = ""
 default[:osqa][:sites] = []
+
+default[:accounts][:users][:osqa][:status] = :role
index 02f870410394bf7b57c1b901dc8f4e8b6086ef24..932a04697bdf149ffdbf33d85e0aa01930c42307 100644 (file)
@@ -6,6 +6,7 @@ description       "Installs and configures OSQA"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
 depends           "memcached"
 depends           "python"
index 6e8d00d4afa128a62fba39ff4af256c415c7b1f1..3a229531f3d1408d79eca5fb295854a31b459ed4 100644 (file)
 # limitations under the License.
 #
 
-include_recipe "tools"
+include_recipe "accounts"
 include_recipe "apache"
 include_recipe "memcached"
 include_recipe "python"
+include_recipe "tools"
 
 package "python-dev"
 package "libmysqlclient-dev"
@@ -28,18 +29,15 @@ package "libpq-dev"
 
 python_directory = "/opt/osqa-python"
 
-python_virtualenv python_directory
+python_virtualenv python_directory do
+  interpreter "/usr/bin/python2"
+end
 
 python_package "Django" do
   python_virtualenv python_directory
   version "1.6.11"
 end
 
-python_package "html5lib" do
-  python_virtualenv python_directory
-  version "0.999"
-end
-
 python_package "Markdown" do
   python_virtualenv python_directory
   version "2.4"
@@ -55,11 +53,6 @@ python_package "python-openid" do
   version "2.2.5"
 end
 
-python_package "MySQL-python" do
-  python_virtualenv python_directory
-  version "1.2.3"
-end
-
 python_package "psycopg2" do
   python_virtualenv python_directory
   version "2.7.6.1"
@@ -70,6 +63,11 @@ python_package "South" do
   version "0.7.6"
 end
 
+python_package "html5lib" do
+  python_virtualenv python_directory
+  version "0.999"
+end
+
 apache_module "rewrite"
 apache_module "wsgi"
 
@@ -100,7 +98,7 @@ node[:osqa][:sites].each do |site|
   directory directory do
     owner site_user
     group site_group
-    mode 0o755
+    mode "755"
   end
 
   execute "osqa-migrate" do
@@ -116,6 +114,7 @@ node[:osqa][:sites].each do |site|
     action :sync
     repository "https://git.openstreetmap.org/public/osqa.git"
     revision "live"
+    depth 1
     user site_user
     group site_group
     notifies :run, "execute[osqa-migrate]"
@@ -124,14 +123,14 @@ node[:osqa][:sites].each do |site|
   directory "#{directory}/upfiles" do
     user site_user
     group site_group
-    mode 0o755
+    mode "755"
   end
 
   template "#{directory}/osqa/osqa.wsgi" do
     source "osqa.wsgi.erb"
     owner site_user
     group site_group
-    mode 0o644
+    mode "644"
     variables :directory => directory
     notifies :reload, "service[apache2]"
   end
@@ -153,7 +152,7 @@ node[:osqa][:sites].each do |site|
   file "#{directory}/osqa/settings_local.py" do
     owner site_user
     group site_group
-    mode 0o644
+    mode "644"
     content settings
     notifies :reload, "service[apache2]"
   end
@@ -162,7 +161,7 @@ node[:osqa][:sites].each do |site|
     source "backup.cron.erb"
     owner "root"
     group "root"
-    mode 0o755
+    mode "755"
     variables :name => backup_name, :directory => directory, :user => site_user, :database => database_name
   end
 end
index 562f687e37d4046a258ca99772f5626eddae2fd2..9aa0eb9cb50463c3c8d6771e1183c1b305e0d01c 100644 (file)
@@ -1,6 +1,6 @@
 # DO NOT EDIT - This file is being maintained by Chef
 
-WSGIDaemonProcess <%= @name %> user=<%= @user %> group=<%= @group %> processes=4 threads=4 inactivity-timeout=600 graceful-timeout=60 maximum-requests=2000 python-home=<%= @python_home %>
+WSGIDaemonProcess <%= @name %> user=<%= @user %> group=<%= @group %> processes=4 threads=8 restart-interval=3600 inactivity-timeout=600 graceful-timeout=60 maximum-requests=2000 python-home=<%= @python_home %>
 
 <VirtualHost *:80>
   ServerName <%= @name %>
index 3c2abf6a79c259a493b56127a96bc75b0291937f..020a035497d6910ef7084151595cd514a03a32cf 100644 (file)
@@ -12,10 +12,9 @@ chown <%= @user %> $T/osqa-$D
 sudo -u <%= @user %> pg_dump --format=custom --file=$T/<%= @name %>-$D/osqa.dmp <%= @database %>
 ln -s <%= @directory %>/upfiles $T/<%= @name %>-$D/upfiles
 
-export GZIP="--rsyncable -9"
 export RSYNC_RSH="ssh -ax"
 
-nice tar --create --gzip --dereference --directory=$T --file=$T/$B <%= @name %>-$D
+nice tar --create --dereference --directory=$T <%= @name %>-$D | nice gzip --rsyncable -9 > $T/$B
 nice rsync --preallocate --fuzzy $T/$B backup::backup
 
 rm -rf $T
index fff2dc008a371c2eb49bc2c1226dc84e30cea493..168a5b9cf0bb603d48cf6036febdb9e3e80176d8 100644 (file)
@@ -1,8 +1,13 @@
-default[:otrs][:version] = "6.0.8"
+default[:otrs][:version] = "6.0.30"
 default[:otrs][:user] = "otrs"
 default[:otrs][:group] = nil
-default[:otrs][:database_cluster] = "9.5/main"
+default[:otrs][:database_cluster] = "10/main"
 default[:otrs][:database_name] = "otrs"
 default[:otrs][:database_user] = "otrs"
-default[:otrs][:database_password] = ""
-default[:otrs][:site] = nil
+default[:otrs][:database_password] = "otrs"
+default[:otrs][:site] = "otrs"
+
+default[:postgresql][:versions] |= ["10"]
+
+default[:accounts][:users][:otrs][:status] = :role
+default[:accounts][:groups][:"www-data"][:members] = [:otrs]
index 39f6087c34da50c83d5fd87d2839c10d5c9b00a9..1cdd780207b2f34564f91b53a68aa41f8f21008e 100644 (file)
@@ -6,6 +6,8 @@ description       "Installs and configures OTRS"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
+depends           "chef"
 depends           "postgresql"
 depends           "tools"
index b5225e2892413b338fc7b7b0f55c546fa84f6490..e235f619cbc99709b4c44570373aafbb5ff5dd43 100644 (file)
 # limitations under the License.
 #
 
-include_recipe "tools"
-include_recipe "postgresql"
+include_recipe "accounts"
 include_recipe "apache"
+include_recipe "postgresql"
+include_recipe "tools"
 
 passwords = data_bag_item("otrs", "passwords")
 
 package "libapache2-mod-perl2"
 package "libapache2-reload-perl"
 
-package "libgd-gd2-perl"
-package "libgd-graph-perl"
-package "libgd-text-perl"
-package "libjson-xs-perl"
-package "libmail-imapclient-perl"
-package "libnet-ldap-perl"
-package "libpdf-api2-perl"
-package "libsoap-lite-perl"
-package "libyaml-libyaml-perl"
-package "libcrypt-eksblowfish-perl"
-package "libtemplate-perl"
+package %w[
+  libcrypt-eksblowfish-perl
+  libdatetime-perl
+  libgd-gd2-perl
+  libgd-graph-perl
+  libgd-text-perl
+  libjson-xs-perl
+  libmail-imapclient-perl
+  libnet-ldap-perl
+  libpdf-api2-perl
+  libsoap-lite-perl
+  libtemplate-perl
+  libyaml-libyaml-perl
+]
 
 apache_module "headers"
 
@@ -61,7 +65,7 @@ end
 
 remote_file "#{Chef::Config[:file_cache_path]}/otrs-#{version}.tar.bz2" do
   source "https://ftp.otrs.org/pub/otrs/otrs-#{version}.tar.bz2"
-  not_if { File.exist?("/opt/otrs-#{version}") }
+  not_if { ::File.exist?("/opt/otrs-#{version}") }
 end
 
 execute "untar-otrs-#{version}" do
@@ -69,7 +73,7 @@ execute "untar-otrs-#{version}" do
   cwd "/opt"
   user "root"
   group "root"
-  not_if { File.exist?("/opt/otrs-#{version}") }
+  not_if { ::File.exist?("/opt/otrs-#{version}") }
 end
 
 config = edit_file "/opt/otrs-#{version}/Kernel/Config.pm.dist" do |line|
@@ -88,7 +92,7 @@ end
 file "/opt/otrs-#{version}/Kernel/Config.pm" do
   owner user
   group "www-data"
-  mode 0o664
+  mode "664"
   content config
 end
 
@@ -104,14 +108,6 @@ execute "/opt/otrs/bin/otrs.SetPermissions.pl" do
   only_if { File.stat("/opt/otrs/README.md").uid != Etc.getpwnam("otrs").uid }
 end
 
-execute "/opt/otrs/bin/otrs.RebuildConfig.pl" do
-  action :run
-  command "/opt/otrs/bin/otrs.RebuildConfig.pl"
-  user "root"
-  group "root"
-  not_if { File.exist?("/opt/otrs/Kernel/Config/Files/ZZZAAuto.pm") }
-end
-
 execute "/opt/otrs/bin/Cron.sh" do
   action :nothing
   command "/opt/otrs/bin/Cron.sh restart"
@@ -125,7 +121,7 @@ Dir.glob("/opt/otrs/var/cron/*.dist") do |distname|
   file name do
     owner "otrs"
     group "www-data"
-    mode 0o664
+    mode "664"
     content IO.read(distname)
     notifies :run, "execute[/opt/otrs/bin/Cron.sh]"
   end
@@ -145,12 +141,12 @@ template "/etc/sudoers.d/otrs" do
   source "sudoers.erb"
   owner "root"
   group "root"
-  mode 0o440
+  mode "440"
 end
 
 template "/etc/cron.daily/otrs-backup" do
   source "backup.cron.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
index bfe5242afb3a34f0eaaaa1e149ffa749b8524270..aecce1c64af1c4feb3ff8e9dce31bff4b5073763 100644 (file)
@@ -13,10 +13,9 @@ sudo -u otrs pg_dump --file=$T/otrs-$D/otrs.dmp otrs
 ln -s /opt/otrs $T/otrs-$D/otrs
 ln -s /etc/apache2/sites-available/otrs.openstreetmap.org.conf $T/otrs-$D/apache2-otrs.openstreetmap.org.conf
 
-export GZIP="--rsyncable -9"
 export RSYNC_RSH="ssh -ax"
 
-nice tar --create --gzip --dereference --directory=$T --file=$T/$B otrs-$D
+nice tar --create --dereference --directory=$T otrs-$D | nice gzip --rsyncable -9 > $T/$B
 nice rsync --preallocate --fuzzy $T/$B backup::backup
 
 rm -rf $T
index 753a8d0999802076e150032d12303c9d3c50ff04..03c6b5a8d13ab44068c0a049089f4003b758b410 100644 (file)
@@ -1,4 +1,9 @@
-default[:passenger][:ruby_version] = "2.5"
+default[:passenger][:ruby_version] = if node[:lsb][:release].to_f < 20.04
+                                       "2.5"
+                                     else
+                                       "2.7"
+                                     end
+
 default[:passenger][:max_pool_size] = 6
 default[:passenger][:pool_idle_time] = 300
 default[:passenger][:instance_registry_dir] = "/run/passenger"
index 24863de8a1533693d3e8c482b972a91d3739fa4c..42fc95c2aa8b7e0acadbc8552ed6ce4f68e7556f 100644 (file)
@@ -7,4 +7,7 @@ description       "Installs and configures passenger"
 version           "1.0.0"
 supports          "ubuntu"
 depends           "apache"
+depends           "apt"
 depends           "munin"
+depends           "prometheus"
+depends           "systemd"
index a9ef419a0259669c1e2e905d95a58b735c12601d..95abd7890847bf82a2be293460b2334364b514f8 100644 (file)
@@ -18,6 +18,9 @@
 #
 
 include_recipe "apache"
+include_recipe "apt"
+include_recipe "munin"
+include_recipe "prometheus"
 
 package "ruby#{node[:passenger][:ruby_version]}"
 package "ruby#{node[:passenger][:ruby_version]}-dev"
@@ -31,7 +34,7 @@ template "/usr/local/bin/passenger-ruby" do
   source "ruby.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   notifies :reload, "service[apache2]"
 end
 
@@ -54,3 +57,8 @@ munin_plugin "passenger_memory"
 munin_plugin "passenger_processes"
 munin_plugin "passenger_queues"
 munin_plugin "passenger_requests"
+
+prometheus_exporter "passenger" do
+  port 9149
+  environment "PASSENGER_INSTANCE_REGISTRY_DIR" => node[:passenger][:instance_registry_dir]
+end
index f2af9a2e86669f002582b80fb07e7d15dbe5f8b2..3eef14c7f8d8c767f69c6595f65dfd2e9e7da029 100644 (file)
@@ -19,7 +19,7 @@
 
 default_action :restart
 
-property :application, String, :name_attribute => true
+property :application, String, :name_property => true
 
 action :restart do
   execute new_resource.application do
diff --git a/cookbooks/php/README.md b/cookbooks/php/README.md
new file mode 100644 (file)
index 0000000..135c7db
--- /dev/null
@@ -0,0 +1,3 @@
+# PHP Cookbook
+
+Installs and configures PHP.
diff --git a/cookbooks/php/attributes/default.rb b/cookbooks/php/attributes/default.rb
new file mode 100644 (file)
index 0000000..ccce260
--- /dev/null
@@ -0,0 +1,7 @@
+default[:php][:version] = if node[:lsb][:release].to_f < 20.04
+                            "7.2"
+                          else
+                            "7.4"
+                          end
+
+default[:php][:fpm][:options] = {}
similarity index 66%
rename from cookbooks/roundup/metadata.rb
rename to cookbooks/php/metadata.rb
index 678654721b4adec0e2b87d4aff794d7a34e6eef6..db4cfc27a6f0f3eb50f6397810b784be1c88f40c 100644 (file)
@@ -1,9 +1,10 @@
-name              "roundup"
+name              "php"
 maintainer        "OpenStreetMap Administrators"
 maintainer_email  "admins@openstreetmap.org"
 license           "Apache-2.0"
-description       "Installs and configures a roundup server"
+description       "Installs and configures PHP"
 
 version           "1.0.0"
 supports          "ubuntu"
 depends           "apache"
+depends           "prometheus"
diff --git a/cookbooks/php/recipes/apache.rb b/cookbooks/php/recipes/apache.rb
new file mode 100644 (file)
index 0000000..dc60248
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# Cookbook:: php
+# Recipe:: apache
+#
+# Copyright:: 2020, OpenStreetMap Foundation
+#
+# 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
+#
+#     https://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.
+#
+
+include_recipe "apache"
+include_recipe "php::fpm"
+
+apache_module "proxy"
+apache_module "proxy_fcgi"
+
+apache_module "php#{node[:php][:version]}" do
+  action :disable
+end
+
+apache_conf "php#{node[:php][:version]}-fpm" do
+  action :enable
+end
similarity index 83%
rename from cookbooks/roundup/recipes/default.rb
rename to cookbooks/php/recipes/default.rb
index 634019c3bff68b56e6911cd22570750d3814f802..3164006a42d4eac19bd1f03481e3ff637bf68204 100644 (file)
@@ -1,8 +1,8 @@
 #
-# Cookbook:: roundup
+# Cookbook:: php
 # Recipe:: default
 #
-# Copyright:: 2013, OpenStreetMap Foundation
+# Copyright:: 2020, OpenStreetMap Foundation
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -16,4 +16,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-include_recipe "apache"
+
+package %W[
+  php
+  php#{node[:php][:version]}-fpm
+]
diff --git a/cookbooks/php/recipes/fpm.rb b/cookbooks/php/recipes/fpm.rb
new file mode 100644 (file)
index 0000000..2bebc87
--- /dev/null
@@ -0,0 +1,35 @@
+#
+# Cookbook:: php
+# Recipe:: fpm
+#
+# Copyright:: 2020, OpenStreetMap Foundation
+#
+# 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
+#
+#     https://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.
+#
+
+include_recipe "php"
+include_recipe "prometheus"
+
+package "php-fpm"
+
+template "/etc/php/#{node[:php][:version]}/fpm/conf.d/99-chef.ini" do
+  source "php-fpm.ini.erb"
+  owner "root"
+  group "root"
+  mode "644"
+  notifies :restart, "service[php#{node[:php][:version]}-fpm]"
+end
+
+service "php#{node[:php][:version]}-fpm" do
+  action [:enable, :start]
+end
diff --git a/cookbooks/php/resources/fpm.rb b/cookbooks/php/resources/fpm.rb
new file mode 100644 (file)
index 0000000..0178e64
--- /dev/null
@@ -0,0 +1,101 @@
+#
+# Cookbook:: php
+# Resource:: php_fpm
+#
+# Copyright:: 2020, OpenStreetMap Foundation
+#
+# 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
+#
+# https://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.
+#
+
+default_action :create
+
+property :pool, :kind_of => String, :name_property => true
+property :port, :kind_of => Integer
+property :user, :kind_of => String, :default => "www-data"
+property :group, :kind_of => String, :default => "www-data"
+property :pm, :kind_of => String, :default => "dynamic"
+property :pm_max_children, :kind_of => Integer, :default => 5
+property :pm_start_servers, :kind_of => Integer, :default => 2
+property :pm_min_spare_servers, :kind_of => Integer, :default => 1
+property :pm_max_spare_servers, :kind_of => Integer, :default => 3
+property :pm_max_requests, :kind_of => Integer, :default => 500
+property :request_terminate_timeout, :kind_of => Integer, :default => 0
+property :environment, :kind_of => Hash, :default => {}
+property :php_values, :kind_of => Hash, :default => {}
+property :php_admin_values, :kind_of => Hash, :default => {}
+property :php_flags, :kind_of => Hash, :default => {}
+property :php_admin_flags, :kind_of => Hash, :default => {}
+property :reload_fpm, :kind_of => [TrueClass, FalseClass], :default => true
+property :prometheus_port, :kind_of => Integer
+
+action :create do
+  template conf_file do
+    cookbook "php"
+    source "pool.conf.erb"
+    owner "root"
+    group "root"
+    mode "644"
+    variables new_resource.to_hash.merge(:pool => new_resource.pool)
+  end
+
+  if new_resource.prometheus_port
+    prometheus_exporter "phpfpm" do
+      port new_resource.prometheus_port
+      service service_name
+      command "server"
+      options "--phpfpm.scrape-uri=#{scrape_uri}"
+    end
+  else
+    prometheus_exporter "phpfpm" do
+      action :delete
+      service service_name
+    end
+  end
+end
+
+action :delete do
+  file conf_file do
+    action :delete
+  end
+
+  prometheus_exporter "phpfpm" do
+    action :delete
+    service service_name
+  end
+end
+
+action_class do
+  def php_version
+    node[:php][:version]
+  end
+
+  def conf_file
+    "/etc/php/#{php_version}/fpm/pool.d/#{new_resource.pool}.conf"
+  end
+
+  def service_name
+    "phpfpm-#{new_resource.pool}"
+  end
+
+  def scrape_uri
+    if new_resource.port
+      "tcp://127.0.0.1:#{new_resource.port}/status"
+    else
+      "unix:///run/php/#{new_resource.pool}.sock;/status"
+    end
+  end
+end
+
+def after_created
+  notifies :reload, "service[php#{node[:php][:version]}-fpm]" if reload_fpm
+end
diff --git a/cookbooks/php/templates/default/php-fpm.ini.erb b/cookbooks/php/templates/default/php-fpm.ini.erb
new file mode 100644 (file)
index 0000000..da34ca3
--- /dev/null
@@ -0,0 +1,5 @@
+; DO NOT EDIT - This file is being maintained by Chef
+
+<% node[:php][:fpm][:options].sort.each do |key,value| -%>
+<%= key %>=<%= value %>
+<% end -%>
diff --git a/cookbooks/php/templates/default/pool.conf.erb b/cookbooks/php/templates/default/pool.conf.erb
new file mode 100644 (file)
index 0000000..1877b7b
--- /dev/null
@@ -0,0 +1,46 @@
+; DO NOT EDIT - This file is being maintained by Chef
+
+[<%= @pool %>]
+<% if @port -%>
+listen = 127.0.0.1:<%= @port %>
+listen.backlog = 256
+<% else -%>
+listen = /run/php/<%= @pool %>.sock
+listen.owner = www-data
+listen.group = www-data
+<% end -%>
+
+user = <%= @user %>
+group = <%= @group %>
+
+pm = <%= @pm %>
+pm.max_children = <%= @pm_max_children %>
+pm.start_servers = <%= @pm_start_servers %>
+pm.min_spare_servers = <%= @pm_min_spare_servers %>
+pm.max_spare_servers = <%= @pm_max_spare_servers %>
+pm.max_requests = <%= @pm_max_requests %>
+pm.status_path = /status
+
+request_terminate_timeout = <%= @request_terminate_timeout %>
+
+security.limit_extensions = .php .phpx .phpj
+
+<% @environment.each do |name, value| -%>
+env[<%= name %>] = <%= value %>
+<% end -%>
+
+<% @php_values.each do |name, value| -%>
+php_value[<%= name %>] = <%= value %>
+<% end -%>
+
+<% @php_admin_values.each do |name, value| -%>
+php_admin_value[<%= name %>] = <%= value %>
+<% end -%>
+
+<% @php_flags.each do |name, value| -%>
+php_flag[<%= name %>] = <%= value %>
+<% end -%>
+
+<% @php_admin_flags.each do |name, value| -%>
+php_admin_flag[<%= name %>] = <%= value %>
+<% end -%>
index 832b728a076288c2301319fe8d964d6f08f5607a..a24fca595d35b039311b01a2586600fd16c581fe 100644 (file)
@@ -1,13 +1,13 @@
-default[:piwik][:version] = "3.11.0"
+default[:piwik][:version] = "4.2.1"
 default[:piwik][:plugins] = %w[
   Actions Annotations API BulkTracking Contents CoreAdminHome CoreConsole
-  CoreHome CorePluginsAdmin CoreUpdater CoreVisualizations CustomPiwikJs
-  CustomVariables Dashboard DevicePlugins DevicesDetection Diagnostics Ecommerce
-  Events Feedback GeoIp2 Goals Heartbeat ImageGraph Insights Installation Intl
-  LanguagesManager Live Login Marketplace MobileMessaging Monolog Morpheus
-  MultiSites Overlay PrivacyManager ProfessionalServices Provider Proxy
-  Referrers Resolution RssWidget ScheduledReports SegmentEditor SEO SitesManager
-  Transitions UserCountry UserCountryMap UserId UserLanguage UsersManager
-  VisitFrequency VisitorInterest VisitsSummary VisitTime WebsiteMeasurable
-  Widgetize
+  CoreHome CorePluginsAdmin CoreUpdater CoreVisualizations CustomJsTracker
+  CustomVariables Dashboard DevicePlugins DevicesDetection Diagnostics
+  Ecommerce Events Feedback GeoIp2 Goals Heartbeat ImageGraph Insights
+  Installation Intl LanguagesManager Live Login Marketplace MobileMessaging
+  Monolog Morpheus MultiSites Overlay PagePerformance PrivacyManager
+  ProfessionalServices Provider Proxy Referrers Resolution RssWidget
+  ScheduledReports SegmentEditor SEO SitesManager Transitions UserCountry
+  UserCountryMap UserId UserLanguage UsersManager VisitFrequency
+  VisitorInterest VisitsSummary VisitTime WebsiteMeasurable Widgetize
 ]
index 1644aa90ac5a2967eb2b58c4cec30232ba9407b0..54054e0e071e0e34589ecb8870d64413098ffe56 100644 (file)
@@ -7,4 +7,6 @@ description       "Installs and configures Piwik"
 version           "1.0.0"
 supports          "ubuntu"
 depends           "apache"
+depends           "geoipupdate"
 depends           "mysql"
+depends           "php"
index 2bd0b97a55ceaad9e9956642a5ddc0d0c17a753f..0bd3ede877e3fad2259b7e5d5370cbfb738acda4 100644 (file)
 #
 
 include_recipe "apache"
+include_recipe "geoipupdate"
 include_recipe "mysql"
+include_recipe "php::fpm"
 
 passwords = data_bag_item("piwik", "passwords")
 
-package "php"
-package "php-cli"
-package "php-curl"
-package "php-mbstring"
-package "php-mysql"
-package "php-gd"
-package "php-xml"
-package "php-apcu"
-
-package "geoipupdate"
+package %w[
+  php-cli
+  php-curl
+  php-mbstring
+  php-mysql
+  php-gd
+  php-xml
+  php-apcu
+  unzip
+]
 
 apache_module "expires"
-apache_module "php7.2"
 apache_module "rewrite"
 
 version = node[:piwik][:version]
@@ -47,7 +48,7 @@ end
 
 remote_file "#{Chef::Config[:file_cache_path]}/piwik-#{version}.zip" do
   source "https://builds.matomo.org/piwik-#{version}.zip"
-  not_if { File.exist?("/opt/piwik-#{version}/piwik") }
+  not_if { ::File.exist?("/opt/piwik-#{version}/piwik") }
 end
 
 execute "unzip-piwik-#{version}" do
@@ -55,7 +56,7 @@ execute "unzip-piwik-#{version}" do
   cwd "/opt/piwik-#{version}"
   user "root"
   group "root"
-  not_if { File.exist?("/opt/piwik-#{version}/piwik") }
+  not_if { ::File.exist?("/opt/piwik-#{version}/piwik") }
 end
 
 execute "/opt/piwik-#{version}/piwik/piwik.js" do
@@ -63,7 +64,7 @@ execute "/opt/piwik-#{version}/piwik/piwik.js" do
   cwd "/opt/piwik-#{version}"
   user "root"
   group "root"
-  not_if { File.exist?("/opt/piwik-#{version}/piwik/piwik.js.gz") }
+  not_if { ::File.exist?("/opt/piwik-#{version}/piwik/piwik.js.gz") }
 end
 
 directory "/opt/piwik-#{version}/piwik/config" do
@@ -89,20 +90,20 @@ directory "/opt/piwik-#{version}/piwik/tmp" do
 end
 
 link "/opt/piwik-#{version}/piwik/misc/GeoLite2-ASN.mmdb" do
-  to "/var/lib/GeoIP/GeoLite2-ASN.mmdb"
+  to "/usr/share/GeoIP/GeoLite2-ASN.mmdb"
 end
 
 link "/opt/piwik-#{version}/piwik/misc/GeoLite2-City.mmdb" do
-  to "/var/lib/GeoIP/GeoLite2-City.mmdb"
+  to "/usr/share/GeoIP/GeoLite2-City.mmdb"
 end
 
 link "/opt/piwik-#{version}/piwik/misc/GeoLite2-Country.mmdb" do
-  to "/var/lib/GeoIP/GeoLite2-Country.mmdb"
+  to "/usr/share/GeoIP/GeoLite2-Country.mmdb"
 end
 
 link "/srv/piwik.openstreetmap.org" do
   to "/opt/piwik-#{version}/piwik"
-  notifies :restart, "service[apache2]"
+  notifies :restart, "service[php#{node[:php][:version]}-fpm]"
 end
 
 mysql_user "piwik@localhost" do
@@ -118,13 +119,16 @@ ssl_certificate "piwik.openstreetmap.org" do
   notifies :reload, "service[apache2]"
 end
 
+php_fpm "piwik.openstreetmap.org" do
+  prometheus_port 9253
+end
+
 apache_site "piwik.openstreetmap.org" do
   template "apache.erb"
 end
 
-template "/etc/cron.d/piwiki" do
-  source "cron.erb"
-  owner "root"
-  group "root"
-  mode "0644"
+cron_d "piwik" do
+  minute "5"
+  user "www-data"
+  command "/usr/bin/php /srv/piwik.openstreetmap.org/console core:archive --quiet --url=https://piwik.openstreetmap.org/"
 end
index 58703f41b53622f73c5db8643bb3abaaa70abdb3..f513ce9c2c8ddfc4d49d2ee9d498669b7fa550b5 100644 (file)
@@ -50,4 +50,8 @@
                ExpiresDefault "access plus 1 week"
                Header set Cache-Control "max-age=604800"
        </FilesMatch>
+
+        <FilesMatch ".+\.ph(ar|p|tml)$">
+                SetHandler "proxy:unix:/run/php/piwik.openstreetmap.org.sock|fcgi://127.0.0.1"
+        </FilesMatch>
 </Directory>
index 3e4b940b81c6ce3d9957923ff906edfe0331e246..bb9b6a9d9088662f596e17146007294d339e8db4 100644 (file)
@@ -11,10 +11,14 @@ charset = "utf8"
 [General]
 force_ssl = 1
 force_ssl_login = 1
+login_allowlist_apply_to_reporting_api_requests = "0"
 proxy_client_headers[] = "HTTP_X_FORWARDED_FOR"
 trusted_hosts[] = "piwik.openstreetmap.org"
 salt = "<%= @passwords['salt'] %>"
 
+[Tracker]
+ignore_visits_cookie_name = "piwik_ignore"
+
 [Plugins]
 <% @plugins.each do |plugin| -%>
 Plugins[] = "<%= plugin %>"
@@ -28,7 +32,6 @@ PluginsInstalled[] = "<%= plugin %>"
 [Plugins_Tracker]
 Plugins_Tracker[] = "Provider"
 Plugins_Tracker[] = "Goals"
-Plugins_Tracker[] = "DoNotTrack"
 Plugins_Tracker[] = "UserCountry"
 Plugins_Tracker[] = "DevicesDetection"
 Plugins_Tracker[] = "UsersManager"
diff --git a/cookbooks/piwik/templates/default/cron.erb b/cookbooks/piwik/templates/default/cron.erb
deleted file mode 100644 (file)
index 2637b2f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-5 * * * * www-data /usr/bin/php /srv/piwik.openstreetmap.org/console core:archive --quiet --url=https://piwik.openstreetmap.org/
index e888b56771753b07ffe0181df39dde1c45cd06a4..f01d8acc4b11744b68c2d19e7ffef3d98fda4b5c 100644 (file)
@@ -1,3 +1,5 @@
+default[:accounts][:users][:planet][:status] = :role
+
 default[:planet][:dump][:xml_directory] = "/store/planet/planet"
 default[:planet][:dump][:xml_history_directory] = "/store/planet/planet/full-history"
 default[:planet][:dump][:pbf_directory] = "/store/planet/pbf"
index 25247379714faa433892abcfaaf899ff9b753b2c..6d1810e63f1fb4d6d76cb6c5d53437ec0632fb94 100644 (file)
@@ -4,10 +4,10 @@ print """
 <html>
  <head>
   <title>OpenStreetMap historical CC BY-SA 2.0 licensed data</title>
-  <link href="/style.css" rel="stylesheet" type="text/css">
+  <link href="https://planet.openstreetmap.org/style.css" rel="stylesheet" type="text/css">
  </head>
  <body>
-<img id="logo" src="/logo.png" alt="OSM logo" width="128" height="128">
+<img id="logo" src="https://planet.openstreetmap.org/logo.png" alt="OSM logo" width="128" height="128">
 <h1>planet.openstreetmap.org - CC BY-SA experimental history files.</h1>
 <p>These files are the last experimental history files produced under the CC BY-SA license. More recent data under the ODbL license is <a href="/planet/full-history/">available here</a>.<p>
 <p>The <tt>full-planet-120401-final.osm.bz2</tt> file is the last dump of data before <a href="https://blog.osmfoundation.org/2012/07/26/automated-redactions-complete/">redactions were run to remove data which could not be released under ODbL</a>. The <tt>full-planet-120601-1150.osm.bz2</tt> is the last dump of data available under CC BY-SA, but after the redactions were run. This means it may have less data in some areas, although many redactions were quickly re-mapped.</p>
index da7004ca10e0b7a58ff0ad60f95f44074e53e954..157c103f094ec9d83fedcd54381cc20f0b40a07c 100644 (file)
@@ -10,7 +10,7 @@ def nice_size(file):
     MB = 1024. * KB
     GB = 1024. * MB
     TB = 1024. * GB
-    
+
     if size < KB:
         size, suffix = size, ''
     elif size < MB:
@@ -21,7 +21,7 @@ def nice_size(file):
         size, suffix = size/GB, 'GB'
     else:
         size, suffix = size/TB, 'TB'
-    
+
     if size < 10:
         return '%.1f %s' % (round(size,1), suffix)
     else:
@@ -44,11 +44,12 @@ def nice_time(time):
     return '%d months' % (time / 2592000.)
 
 def file_info(file, name):
+    torrent_file = file + '.torrent'
     size = nice_size(file)
     hash = search(r'\w{32}', open(file+'.md5', 'r').read()).group(0)
     date = nice_time(time() - stat(file).st_mtime)
 
-    return '<b><a href="%(file)s">%(name)s</a></b><br><b>%(size)s</b>, created %(date)s ago.<br><small>md5: %(hash)s</small>.' % locals()
+    return '<b><a href="%(file)s">%(name)s</a> (<a href="%(torrent_file)s">torrent</a>)</b><br><b>%(size)s</b>, created %(date)s ago.<br><small>md5: %(hash)s</small>.' % locals()
 
 planet_link = file_info('planet/planet-latest.osm.bz2', 'Latest Weekly Planet XML File')
 changesets_link = file_info('planet/changesets-latest.osm.bz2', 'Latest Weekly Changesets')
@@ -59,17 +60,17 @@ print """
 <html>
  <head>
   <title>Index of /</title>
-  <link href="style.css" rel="stylesheet" type="text/css">
+  <link href="https://planet.openstreetmap.org/style.css" rel="stylesheet" type="text/css">
  </head>
  <body>
-<img id="logo" src="logo.png" alt="OSM logo" width="128" height="128">
+<img id="logo" src="https://planet.openstreetmap.org/logo.png" alt="OSM logo" width="128" height="128">
 <h1>Planet OSM</h1>
 
 <p>
 The files found here are regularly-updated, complete copies of the OpenStreetMap.org
 database, and those published before the 12 September 2012 are distributed under a Creative Commons Attribution-ShareAlike 2.0 license, those published after are  Open Data Commons Open Database License 1.0 licensed. For more information, <a href="https://wiki.openstreetmap.org/wiki/Planet.osm">see the project wiki</a>.
 </p>
-
+<p><div class="alert"><strong>WARNING</strong> Download speeds are currently restricted to 4096 KB/s due to limited available capacity on our Internet connection. <a href="https://wiki.openstreetmap.org/wiki/Planet.osm#BitTorrent">Please use torrents</a> or <a href="https://wiki.openstreetmap.org/wiki/Planet.osm#Planet.osm_mirrors">a mirror</a> if possible.</div></p>
 <table id="about">
   <tr>
     <th>
@@ -101,8 +102,8 @@ database, and those published before the 12 September 2012 are distributed under
     </td>
     <td>
         <p>
-        You are granted permission to use OpenStreetMap data by 
-        <a href="https://osm.org/copyright">the OpenStreetMap License</a>, which also describes 
+        You are granted permission to use OpenStreetMap data by
+        <a href="https://osm.org/copyright">the OpenStreetMap License</a>, which also describes
         your obligations.
         </p>
         <p>
@@ -113,9 +114,8 @@ database, and those published before the 12 September 2012 are distributed under
         is a tool for importing the data into a Postgis database for rendering maps.
         </p>
         <p>
-        <a href="https://wiki.openstreetmap.org/wiki/Coastline_error_checker">Processed coastline data</a>
-        derived from OSM data is also needed for rendering usable maps, and can be found in a
-        <a href="historical-shapefiles/processed_p.tar.bz2">single shapefile</a> (360MB).
+        <a href="https://osmdata.openstreetmap.de/">Processed coastline data</a>
+        derived from OSM data is also needed for rendering usable maps.
         </p>
     </td>
     <td>
index 51ac8458141d10f6f9f77b9e4e38f92eda373698..b713338cbcef6f345906f0001dd94a07ca372a9a 100755 (executable)
@@ -10,7 +10,7 @@ def nice_size(file):
     MB = 1024. * KB
     GB = 1024. * MB
     TB = 1024. * GB
-    
+
     if size < KB:
         size, suffix = size, ''
     elif size < MB:
@@ -21,7 +21,7 @@ def nice_size(file):
         size, suffix = size/GB, 'GB'
     else:
         size, suffix = size/TB, 'TB'
-    
+
     if size < 10:
         return '%.1f %s' % (round(size,1), suffix)
     else:
@@ -44,11 +44,12 @@ def nice_time(time):
     return '%d months' % (time / 2592000.)
 
 def file_info(file, name):
+    torrent_file = file + '.torrent'
     size = nice_size(file)
     hash = search(r'\w{32}', open(file+'.md5', 'r').read()).group(0)
     date = nice_time(time() - stat(file).st_mtime)
 
-    return '<b><a href="%(file)s">%(name)s</a></b><br><b>%(size)s</b>, created %(date)s ago.<br><small>md5: %(hash)s</small>.' % locals()
+    return '<b><a href="%(file)s">%(name)s</a> (<a href="%(torrent_file)s">torrent</a>)</b><br><b>%(size)s</b>, created %(date)s ago.<br><small>md5: %(hash)s</small>.' % locals()
 
 planet_link = file_info('history-latest.osm.bz2', 'Latest Full History Planet XML File')
 planet_pbf_link = file_info('../../pbf/full-history/history-latest.osm.pbf', 'Latest Full History Planet PBF File')
@@ -58,16 +59,16 @@ print """
 <html>
  <head>
   <title>Index of /planet/full-history</title>
-  <link href="../../style.css" rel="stylesheet" type="text/css">
+  <link href="https://planet.openstreetmap.org/style.css" rel="stylesheet" type="text/css">
  </head>
  <body>
-<img id="logo" src="../../logo.png" alt="OSM logo" width="128" height="128">
+<img id="logo" src="https://planet.openstreetmap.org/logo.png" alt="OSM logo" width="128" height="128">
 <h1>Planet OSM</h1>
 
 <p>
 The files found here are complete copies of the OpenStreetMap.org
-database, including editing history. These are published under an 
-Open Data Commons Open Database License 1.0 licensed. For more 
+database, including editing history. These are published under an
+Open Data Commons Open Database License 1.0 licensed. For more
 information, <a href="https://wiki.openstreetmap.org/wiki/Planet.osm/full">see the project wiki</a>.
 </p>
 
@@ -94,13 +95,13 @@ information, <a href="https://wiki.openstreetmap.org/wiki/Planet.osm/full">see t
     </td>
     <td>
         <p>
-        You are granted permission to use OpenStreetMap data by 
-        <a href="https://osm.org/copyright">the OpenStreetMap License</a>, which also describes 
+        You are granted permission to use OpenStreetMap data by
+        <a href="https://osm.org/copyright">the OpenStreetMap License</a>, which also describes
         your obligations.
         </p>
         <p>
         You can <a href="https://wiki.openstreetmap.org/wiki/Planet.osm/full#Processing">process the file</a>
-        or extracts with a variety of tools, although some tools for processing OSM data will 
+        or extracts with a variety of tools, although some tools for processing OSM data will
        only work on 'current' planets and will not process a 'history' planet available here.
         </p>
     </td>
@@ -108,7 +109,7 @@ information, <a href="https://wiki.openstreetmap.org/wiki/Planet.osm/full">see t
         <p>
         The complete history planet is extremely large, so you may prefer to use one of
         <a href="https://wiki.openstreetmap.org/wiki/Planet.osm/full#Extracts">the available extracts</a>
-        (individual countries or states) from third parties. 
+        (individual countries or states) from third parties.
         </p>
     </td>
   </tr>
index 3f3940cbcc8cfa3b6cb627da9535eff99b9fb9bf..806b5ec1853752e627c00776700851f4c02fe04e 100644 (file)
@@ -1,8 +1,7 @@
-#No bz2 chomping bots please
+# No bz2 chomping bots please
 
 User-agent: wget
 Allow: /
 
 User-agent: *
 Disallow: /
-
index 0a7afa9d0b25020d3314d493298dc22d1339c970..600622fa268f37a73011d3be60958c09c7bfeb77 100644 (file)
@@ -52,3 +52,10 @@ table#about tr td
     font-size: 100%;
     white-space: normal;
 }
+
+.alert {
+  padding: 20px;
+  background-color: #ff9800; /* Orange */
+  color: white;
+  margin-bottom: 15px;
+}
index 29131b2edd27c2394fb5d83f76157912d90a58ec..77dc83312e946354415b09112f1952ebffa550d7 100755 (executable)
@@ -261,8 +261,13 @@ class Replicator
 
   # saves new state (including the changeset dump xml)
   def save!
-    File.open(@config["state_file"], "r") do |fl|
-      fl.flock(File::LOCK_EX)
+    File.open(@config["lock_file"], File::RDWR | File::CREAT, 0o600) do |fl|
+      # take the lock in non-blocking mode. if this process doesn't get the lock
+      # then another will be run from cron shortly. this prevents a whole bunch
+      # of processes queueing on the lock and causing weirdness if/when they
+      # get woken up in a random order.
+      got_lock = fl.flock(File::LOCK_EX | File::LOCK_NB)
+      return unless got_lock
 
       # try and write the files to tmp locations and then
       # move them into place later, to avoid in-progress
index edde59d2774e94f6c6f005aaaeaeceed9899eee2..269ce0f7235d0fde11398ba6892f22ab33ad77af 100644 (file)
@@ -4,10 +4,10 @@ print """
 <html>
  <head>
   <title>OpenStreetMap replication diffs</title>
-  <link href="/style.css" rel="stylesheet" type="text/css">
+  <link href="https://planet.openstreetmap.org/style.css" rel="stylesheet" type="text/css">
  </head>
  <body>
-<img id="logo" src="/logo.png" alt="OSM logo" width="128" height="128">
+<img id="logo" src="https://planet.openstreetmap.org/logo.png" alt="OSM logo" width="128" height="128">
 <h1>planet.openstreetmap.org - replication diffs</h1>
 <p>OpenStreetMap is <i>open data</i>, licensed under the <a href="https://opendatacommons.org/licenses/odbl/">Open Data Commons Open Database License</a> (ODbL)</p>
 <p>&nbsp;</p>
index 97cd99ffb8044a2c3b1f77af8a2fb262a33c0344..6bc12d40fb8dccf0c44358d53bb1ecd6ea25725a 100644 (file)
@@ -6,8 +6,11 @@ description       "Installs and configures a planet server"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
+depends           "apt"
 depends           "git"
-depends           "osmosis"
 depends           "incron"
 depends           "munin"
+depends           "osmosis"
+depends           "systemd"
index 7e2e50f1d32a258604f65b8fb5b534929a7e6397..fefcaaad7d48433d310175ba1ab7464d1f8a5726 100644 (file)
@@ -17,6 +17,8 @@
 # limitations under the License.
 #
 
+include_recipe "accounts"
+
 package %w[
   pyosmium
 ]
@@ -25,40 +27,41 @@ template "/usr/local/bin/planet-update" do
   source "planet-update.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 template "/usr/local/bin/planet-update-file" do
   source "planet-update-file.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 directory "/var/lib/planet" do
   owner "planet"
   group "planet"
-  mode 0o755
+  mode "755"
 end
 
-remote_file "/var/lib/planet/planet.pbf" do
+remote_file "/var/lib/planet/planet.osh.pbf" do
   action :create_if_missing
-  source "https://planet.openstreetmap.org/pbf/planet-latest.osm.pbf"
+  source "https://planet.openstreetmap.org/pbf/full-history/history-latest.osm.pbf"
   owner "planet"
   group "planet"
-  mode 0o644
+  mode "644"
+  not_if { ENV["TEST_KITCHEN"] }
 end
 
-template "/etc/cron.d/planet-update" do
-  source "planet-update.cron.erb"
-  owner "root"
-  group "root"
-  mode 0o644
+cron_d "planet-update" do
+  minute "17"
+  hour "1"
+  user "root"
+  command "/usr/local/bin/planet-update"
 end
 
 template "/etc/logrotate.d/planet-update" do
   source "planet-update.logrotate.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
index 28b1abdb8d6f6bfb0790c196938257fd14930cf2..b99b4ab0b54174e18cc4540d73c2c6c16efd277f 100644 (file)
 # limitations under the License.
 #
 
+include_recipe "accounts"
 include_recipe "apache"
+include_recipe "munin"
 
-package "perl"
-package "pbzip2"
-package "osmosis"
-
-package "php-cli"
-
-file "/etc/cron.d/planet" do
-  action :delete
-end
+package %w[
+  perl
+  php-cli
+]
 
 remote_directory "/store/planet#html" do
   path "/store/planet"
@@ -37,7 +34,7 @@ remote_directory "/store/planet#html" do
   mode "0755"
   files_owner "root"
   files_group "root"
-  files_mode 0o644
+  files_mode "644"
 end
 
 remote_directory "/store/planet#cgi" do
@@ -45,30 +42,30 @@ remote_directory "/store/planet#cgi" do
   source "cgi"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   files_owner "root"
   files_group "root"
-  files_mode 0o755
+  files_mode "755"
 end
 
 remote_directory node[:planet][:dump][:xml_history_directory] do
   source "history_cgi"
   owner "www-data"
   group "planet"
-  mode 0o775
+  mode "775"
   files_owner "root"
   files_group "root"
-  files_mode 0o755
+  files_mode "755"
 end
 
 remote_directory "/store/planet/cc-by-sa/full-experimental" do
   source "ccbysa_history_cgi"
   owner "www-data"
   group "planet"
-  mode 0o775
+  mode "775"
   files_owner "root"
   files_group "root"
-  files_mode 0o755
+  files_mode "755"
 end
 
 [:xml_directory, :xml_history_directory,
@@ -76,27 +73,28 @@ end
   directory node[:planet][:dump][dir] do
     owner "www-data"
     group "planet"
-    mode 0o775
+    mode "775"
   end
 end
 
 directory "/store/planet/notes" do
   owner "www-data"
   group "planet"
-  mode 0o775
+  mode "775"
 end
 
 template "/usr/local/bin/apache-latest-planet-filename" do
   source "apache-latest-planet-filename.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   notifies :restart, "service[apache2]"
 end
 
 apache_module "cgid"
 apache_module "rewrite"
 apache_module "proxy_http"
+apache_module "ratelimit"
 
 ssl_certificate "planet.openstreetmap.org" do
   domains ["planet.openstreetmap.org", "planet.osm.org"]
@@ -111,7 +109,7 @@ template "/etc/logrotate.d/apache2" do
   source "logrotate.apache.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 munin_plugin "planet_age"
@@ -120,12 +118,15 @@ template "/usr/local/bin/old-planet-file-cleanup" do
   source "old-planet-file-cleanup.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
-template "/etc/cron.d/old-planet-file-cleanup" do
-  source "old-planet-file-cleanup.cron.erb"
-  owner "root"
-  group "root"
-  mode 0o644
+cron_d "old-planet-file-cleanup" do
+  comment "run this on the first monday of the month at 3:44am"
+  minute "44"
+  hour "3"
+  day "1-7"
+  user "www-data"
+  command "test $(date +\\%u) -eq 1 && /usr/local/bin/old-planet-file-cleanup --debug"
+  mailto "zerebubuth@gmail.com"
 end
index 0b46a2c7bcdc65fc21eaea011bbde438d88c2e5a..409d100b1eb8189a1f96fcf9632e08be91f30bfe 100644 (file)
 #
 
 node.default[:incron][:planetdump] = {
-  :user => "www-data",
+  :user => "root",
   :path => "/store/backup",
   :events => %w[IN_CREATE IN_MOVED_TO],
-  :command => "/usr/local/bin/planetdump $#"
+  :command => "/bin/systemctl start planetdump@$#"
 }
 
 include_recipe "git"
 include_recipe "incron"
 
-package "gcc"
-package "make"
-package "autoconf"
-package "automake"
-package "libxml2-dev"
-package "libboost-dev"
-package "libboost-program-options-dev"
-package "libboost-date-time-dev"
-package "libboost-filesystem-dev"
-package "libboost-thread-dev"
-package "libboost-iostreams-dev"
-package "libosmpbf-dev"
-package "libprotobuf-dev"
-package "osmpbf-bin"
-
-# Add planet-mirror-redirect-update dependencies
-package "php-cli"
-package "php-curl"
+package %w[
+  gcc
+  g++
+  make
+  autoconf
+  automake
+  pkg-config
+  libxml2-dev
+  libboost-dev
+  libboost-program-options-dev
+  libboost-date-time-dev
+  libboost-filesystem-dev
+  libboost-thread-dev
+  libboost-iostreams-dev
+  libosmpbf-dev
+  libprotobuf-dev
+  osmpbf-bin
+  pbzip2
+  php-cli
+  php-curl
+  mktorrent
+]
 
 directory "/opt/planet-dump-ng" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 git "/opt/planet-dump-ng" do
   action :sync
-  repository "git://github.com/zerebubuth/planet-dump-ng.git"
-  revision "v1.1.6"
+  repository "https://github.com/zerebubuth/planet-dump-ng.git"
+  revision "v1.2.0"
+  depth 1
   user "root"
   group "root"
 end
@@ -90,7 +95,8 @@ end
 directory "/store/planetdump" do
   owner "www-data"
   group "www-data"
-  mode 0o755
+  mode "755"
+  recursive true
 end
 
 %w[planetdump planet-mirror-redirect-update].each do |program|
@@ -98,13 +104,26 @@ end
     source "#{program}.erb"
     owner "root"
     group "root"
-    mode 0o755
+    mode "755"
   end
 end
 
-template "/etc/cron.d/planet-dump-mirror" do
-  source "planet-dump-mirror-cron.erb"
-  owner "root"
-  group "root"
-  mode 0o644
+systemd_service "planetdump@" do
+  description "Planet dump for %i"
+  user "www-data"
+  exec_start "/usr/local/bin/planetdump %i"
+  memory_max "64G"
+  private_tmp true
+  private_devices true
+  private_network true
+  protect_system "full"
+  protect_home true
+  no_new_privileges true
+end
+
+cron_d "planet-dump-mirror" do
+  minute "*/10"
+  user "www-data"
+  command "/usr/local/bin/planet-mirror-redirect-update"
+  mailto "horntail-www-data-cron@firefishy.com"
 end
index 41303fe43e30dc6d2eea64abebcee685e2f0997f..bccbb0fcf11a3fca95f431d0ffae851b3873dcbf 100644 (file)
@@ -21,18 +21,23 @@ include_recipe "git"
 
 db_passwords = data_bag_item("db", "passwords")
 
-package "python-psycopg2"
-package "python-lxml"
+package %w[
+  pbzip2
+  python3
+  python3-psycopg2
+  python3-lxml
+]
 
 directory "/opt/planet-notes-dump" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 git "/opt/planet-notes-dump" do
   action :sync
-  repository "git://github.com/openstreetmap/planet-notes-dump.git"
+  repository "https://github.com/openstreetmap/planet-notes-dump.git"
+  depth 1
   user "root"
   group "root"
 end
@@ -41,13 +46,23 @@ template "/usr/local/bin/planet-notes-dump" do
   source "planet-notes-dump.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   variables :password => db_passwords["planetdump"]
 end
 
-template "/etc/cron.d/planet-notes-dump" do
-  source "planet-notes-dump.cron.erb"
-  owner "root"
-  group "root"
-  mode 0o644
+cron_d "planet-notes-dump" do
+  minute "0"
+  hour "3"
+  user "www-data"
+  command "/usr/local/bin/planet-notes-dump"
+  mailto "grant-smaug@firefishy.com"
+end
+
+cron_d "planet-notes-cleanup" do
+  comment "Delete Planet Notes dump files older than 8 days"
+  minute "10"
+  hour "8"
+  user "www-data"
+  command "find /store/planet/notes/20??/ -maxdepth 1 -type f -iname 'planet-notes-??????.osn*' -printf '\%T@ \%p\n' | sort -k 1nr | sed 's/^[^ ]* //' | tail -n +17 | xargs -r rm -f"
+  mailto "grant-smaug@firefishy.com"
 end
index 548ae871bdf920d20b8c99d9db5814951b529090..d25197171412538e41ef77475d5a96429f2b20b5 100644 (file)
 # limitations under the License.
 #
 
+require "yaml"
+
+include_recipe "accounts"
+include_recipe "apt"
 include_recipe "osmosis"
 
 db_passwords = data_bag_item("db", "passwords")
 
-package "postgresql-client"
+## Install required packages
 
-package "ruby"
-package "ruby-dev"
-package "ruby-libxml"
+package %w[
+  postgresql-client
+  ruby
+  ruby-dev
+  ruby-libxml
+  make
+  gcc
+  libc6-dev
+  libpq-dev
+  osmdbt
+]
 
-package "libpq-dev"
 gem_package "pg"
 
-package "make"
-package "gcc"
+## Build preload library to flush files
 
 remote_directory "/opt/flush" do
   source "flush"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   files_owner "root"
   files_group "root"
-  files_mode 0o755
+  files_mode "755"
 end
 
 execute "/opt/flush/Makefile" do
@@ -52,190 +62,327 @@ execute "/opt/flush/Makefile" do
   subscribes :run, "remote_directory[/opt/flush]"
 end
 
+## Install scripts
+
 remote_directory "/usr/local/bin" do
   source "replication-bin"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   files_owner "root"
   files_group "root"
-  files_mode 0o755
+  files_mode "755"
+end
+
+template "/usr/local/bin/replicate-minute" do
+  source "replicate-minute.erb"
+  owner "root"
+  group "root"
+  mode "755"
 end
 
 template "/usr/local/bin/users-agreed" do
   source "users-agreed.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 template "/usr/local/bin/users-deleted" do
   source "users-deleted.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
+## Published deleted users directory
+
 remote_directory "/store/planet/users_deleted" do
   source "users_deleted"
   owner "planet"
   group "planet"
-  mode 0o755
+  mode "755"
   files_owner "root"
   files_group "root"
-  files_mode 0o644
+  files_mode "644"
 end
 
+## Published replication directory
+
 remote_directory "/store/planet/replication" do
   source "replication-cgi"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   files_owner "root"
   files_group "root"
-  files_mode 0o755
+  files_mode "755"
 end
 
-directory "/store/planet/replication/changesets" do
-  owner "planet"
-  group "planet"
-  mode 0o755
+## Configuration directory
+
+directory "/etc/replication" do
+  owner "root"
+  group "root"
+  mode "755"
 end
 
-directory "/store/planet/replication/day" do
+## Transient state directory
+
+systemd_tmpfile "/run/replication" do
+  type "d"
   owner "planet"
   group "planet"
-  mode 0o755
+  mode "755"
 end
 
-directory "/store/planet/replication/hour" do
+## Persistent state directory
+
+directory "/var/lib/replication" do
   owner "planet"
   group "planet"
-  mode 0o755
+  mode "755"
 end
 
-directory "/store/planet/replication/minute" do
+## Temporary directory
+
+directory "/store/replication" do
   owner "planet"
   group "planet"
-  mode 0o755
+  mode "755"
 end
 
-directory "/etc/replication" do
-  owner "root"
-  group "root"
-  mode 0o755
-end
+## Users replication
 
-template "/etc/replication/auth.conf" do
-  source "replication.auth.erb"
-  user "root"
+template "/etc/replication/users-agreed.conf" do
+  source "users-agreed.conf.erb"
+  user "planet"
   group "planet"
-  mode 0o640
+  mode "600"
   variables :password => db_passwords["planetdiff"]
 end
 
+## Changeset replication
+
+directory "/store/planet/replication/changesets" do
+  owner "planet"
+  group "planet"
+  mode "755"
+end
+
 template "/etc/replication/changesets.conf" do
   source "changesets.conf.erb"
   user "root"
   group "planet"
-  mode 0o640
+  mode "640"
   variables :password => db_passwords["planetdiff"]
 end
 
-template "/etc/replication/users-agreed.conf" do
-  source "users-agreed.conf.erb"
-  user "planet"
+## Minutely replication
+
+directory "/store/planet/replication/minute" do
+  owner "planet"
   group "planet"
-  mode 0o600
-  variables :password => db_passwords["planetdiff"]
+  mode "755"
 end
 
-directory "/var/lib/replication" do
+directory "/var/lib/replication/minute" do
   owner "planet"
   group "planet"
-  mode 0o755
+  mode "755"
+end
+
+directory "/store/replication/minute" do
+  owner "planet"
+  group "planet"
+  mode "755"
+end
+
+osmdbt_config = {
+  "database" => {
+    "host" => node[:web][:database_host],
+    "dbname" => "openstreetmap",
+    "user" => "planetdiff",
+    "password" => db_passwords["planetdiff"],
+    "replication_slot" => "osmdbt"
+  },
+  "log_dir" => "/var/lib/replication/minute",
+  "changes_dir" => "/store/planet/replication/minute",
+  "tmp_dir" => "/store/replication/minute",
+  "run_dir" => "/run/replication"
+}
+
+file "/etc/replication/osmdbt-config.yaml" do
+  user "root"
+  group "planet"
+  mode "640"
+  content YAML.dump(osmdbt_config)
+end
+
+systemd_service "replication-minutely" do
+  description "Minutely replication"
+  user "planet"
+  working_directory "/etc/replication"
+  exec_start "/usr/local/bin/replicate-minute"
+  private_tmp true
+  private_devices true
+  protect_system "full"
+  protect_home true
+  restrict_address_families %w[AF_INET AF_INET6]
+  no_new_privileges true
+end
+
+systemd_timer "replication-minutely" do
+  description "Minutely replication"
+  on_boot_sec 60
+  on_unit_active_sec 60
+  accuracy_sec 5
+end
+
+## Hourly replication
+
+directory "/store/planet/replication/hour" do
+  owner "planet"
+  group "planet"
+  mode "755"
 end
 
 directory "/var/lib/replication/hour" do
   owner "planet"
   group "planet"
-  mode 0o755
+  mode "755"
+end
+
+link "/var/lib/replication/hour/data" do
+  to "/store/planet/replication/hour"
 end
 
 template "/var/lib/replication/hour/configuration.txt" do
   source "replication.config.erb"
   owner "planet"
   group "planet"
-  mode 0o644
+  mode "644"
   variables :base => "minute", :interval => 3600
 end
 
-link "/var/lib/replication/hour/data" do
-  to "/store/planet/replication/hour"
+systemd_service "replication-hourly" do
+  description "Hourly replication"
+  user "planet"
+  exec_start "/usr/local/bin/osmosis -q --merge-replication-files workingDirectory=/var/lib/replication/hour"
+  private_tmp true
+  private_devices true
+  protect_system "full"
+  protect_home true
+  restrict_address_families %w[AF_INET AF_INET6]
+  no_new_privileges true
+end
+
+systemd_timer "replication-hourly" do
+  description "Daily replication"
+  on_calendar "*-*-* *:02/15:00"
+end
+
+## Daily replication
+
+directory "/store/planet/replication/day" do
+  owner "planet"
+  group "planet"
+  mode "755"
 end
 
 directory "/var/lib/replication/day" do
   owner "planet"
   group "planet"
-  mode 0o755
+  mode "755"
+end
+
+link "/var/lib/replication/day/data" do
+  to "/store/planet/replication/day"
 end
 
 template "/var/lib/replication/day/configuration.txt" do
   source "replication.config.erb"
   owner "planet"
   group "planet"
-  mode 0o644
+  mode "644"
   variables :base => "hour", :interval => 86400
 end
 
-link "/var/lib/replication/day/data" do
-  to "/store/planet/replication/day"
+systemd_service "replication-daily" do
+  description "Daily replication"
+  user "planet"
+  exec_start "/usr/local/bin/osmosis -q --merge-replication-files workingDirectory=/var/lib/replication/day"
+  private_tmp true
+  private_devices true
+  protect_system "full"
+  protect_home true
+  restrict_address_families %w[AF_INET AF_INET6]
+  no_new_privileges true
 end
 
+systemd_timer "replication-daily" do
+  description "Daily replication"
+  on_calendar "*-*-* *:02/15:00"
+end
+
+## Enable/disable feeds
+
 if node[:planet][:replication] == "enabled"
-  template "/etc/cron.d/replication" do
-    source "replication.cron.erb"
-    owner "root"
-    group "root"
-    mode 0o644
+  cron_d "users-agreed" do
+    minute "0"
+    hour "7"
+    user "planet"
+    command "/usr/local/bin/users-agreed"
+    mailto "zerebubuth@gmail.com"
+  end
+
+  cron_d "users-deleted" do
+    minute "0"
+    hour "17"
+    user "planet"
+    command "/usr/local/bin/users-deleted"
+    mailto "zerebubuth@gmail.com"
+  end
+
+  cron_d "replication-changesets" do
+    user "planet"
+    command "/usr/local/bin/replicate-changesets /etc/replication/changesets.conf"
+    mailto "zerebubuth@gmail.com"
+  end
+
+  service "replication-minutely.timer" do
+    action [:enable, :start]
+  end
+
+  service "replication-hourly.timer" do
+    action [:enable, :start]
+  end
+
+  service "replication-daily.timer" do
+    action [:enable, :start]
   end
 else
-  file "/etc/cron.d/replication" do
+  cron_d "users-agreed" do
     action :delete
   end
-end
 
-# directory "/var/lib/replication/streaming" do
-#   owner "planet"
-#   group "planet"
-#   mode 0o755
-# end
-#
-# directory "/var/log/replication" do
-#   owner "planet"
-#   group "planet"
-#   mode 0o755
-# end
-#
-# ["streaming-replicator", "streaming-server"].each do |name|
-#   template "/etc/init.d/#{name}" do
-#     source "streaming.init.erb"
-#     owner "root"
-#     group "root"
-#     mode 0o755
-#     variables :service => name
-#   end
-#
-#   if node[:planet][:replication] == "enabled"
-#     service name do
-#       action [:enable, :start]
-#       supports :restart => true, :status => true
-#       subscribes :restart, "template[/etc/init.d/#{name}]"
-#     end
-#   else
-#     service name do
-#       action [:disable, :stop]
-#       supports :restart => true, :status => true
-#     end
-#   end
-# end
+  cron_d "users-deleted" do
+    action :delete
+  end
+
+  cron_d "replication-changesets" do
+    action :delete
+  end
+
+  service "replication-minutely.timer" do
+    action [:stop, :disable]
+  end
+
+  service "replication-hourly.timer" do
+    action [:stop, :disable]
+  end
+
+  service "replication-daily.timer" do
+    action [:stop, :disable]
+  end
+end
index a67189a0dbb9df8065442de41823c9d2a7a4604f..f8bf0dc7eb0533499295bb79ca081e45d0c56a8f 100644 (file)
         RewriteCond %{QUERY_STRING} nomirror
         RewriteRule    .*      - [L]
 
-        RewriteRule ^(/planet/planet\-latest\.osm\.bz2)$                ${latestplanet:$1} [R,L]
-        RewriteRule ^(/planet/full\-history/history\-latest\.osm\.bz2)$ ${latestplanet:$1} [R,L]
-        RewriteRule ^(/planet/changesets\-latest\.osm\.bz2)$            ${latestplanet:$1} [R,L]
-        RewriteRule ^(/planet/discussions\-latest\.osm\.bz2)$           ${latestplanet:$1} [R,L]
+        RewriteRule ^(/planet/planet\-latest\.osm\.bz2(\.torrent)?)$                ${latestplanet:$1} [R,L]
+        RewriteRule ^(/planet/full\-history/history\-latest\.osm\.bz2(\.torrent)?)$ ${latestplanet:$1} [R,L]
+        RewriteRule ^(/planet/changesets\-latest\.osm\.bz2(\.torrent)?)$            ${latestplanet:$1} [R,L]
+        RewriteRule ^(/planet/discussions\-latest\.osm\.bz2(\.torrent)?)$           ${latestplanet:$1} [R,L]
 
-        RewriteRule ^(/pbf/planet\-latest\.osm\.pbf)$                   ${latestplanet:$1} [R,L]
-        RewriteRule ^(/pbf/full\-history/history\-latest\.osm\.pbf)$    ${latestplanet:$1} [R,L]
+        RewriteRule ^(/pbf/planet\-latest\.osm\.pbf(\.torrent)?)$                   ${latestplanet:$1} [R,L]
+        RewriteRule ^(/pbf/full\-history/history\-latest\.osm\.pbf(\.torrent)?)$    ${latestplanet:$1} [R,L]
 
         RewriteRule ^(/cc\-by\-sa/pbf/planet\-latest\.osm\.pbf)$        ${latestplanet:$1} [R,L]
         RewriteRule ^(/cc\-by\-sa/planet\-latest\.osm\.bz2)$            ${latestplanet:$1} [R,L]
         RewriteRule ^(/cc\-by\-sa/changesets\-latest\.osm\.bz2)$        ${latestplanet:$1} [R,L]
         RewriteRule ^(/cc\-by\-sa/relations\-latest\.osm\.bz2)$         ${latestplanet:$1} [R,L]
 
+        # Block an abusive fake user agent
+        RewriteCond %{HTTP_USER_AGENT} "=Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36"
+        RewriteRule /.*$ - [F,L]
+
+        # Temporary download rate limit due to upstream fibre connection issues. - 13 Jan 2020
+        <FilesMatch ".+\.(7z|bz2|gz|pbf|tgz|xz)$">
+          SetOutputFilter RATE_LIMIT
+          SetEnv rate-limit 4096
+          SetEnv rate-initial-burst 8192
+        </FilesMatch>
 </VirtualHost>
 
 <VirtualHost *:80>
index 309f253b49638720077e3f01bfba988567a8fd1c..48422054f4459fc8f72895d973a07659437c0f5e 100644 (file)
@@ -1,3 +1,4 @@
 state_file: /store/planet/replication/changesets/state.yaml
 db: host=<%= node[:web][:database_host] %> dbname=openstreetmap user=planetdiff password=<%= @password %>
 data_dir: /store/planet/replication/changesets
+lock_file: /run/replication/changesets.lock
diff --git a/cookbooks/planet/templates/default/old-planet-file-cleanup.cron.erb b/cookbooks/planet/templates/default/old-planet-file-cleanup.cron.erb
deleted file mode 100644 (file)
index 4c880b4..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-MAILTO=zerebubuth@gmail.com
-# run this on the first monday of the month at 3:44am
-44 3 1-7 * * www-data test $(date +\%u) -eq 1 && /usr/local/bin/old-planet-file-cleanup --debug
diff --git a/cookbooks/planet/templates/default/planet-dump-mirror-cron.erb b/cookbooks/planet/templates/default/planet-dump-mirror-cron.erb
deleted file mode 100644 (file)
index 3feec3f..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-MAILTO=horntail-www-data-cron@firefishy.com
-20 */2 * * * www-data /usr/local/bin/planet-mirror-redirect-update
index 81c9f2ae3d260a2c5a819a213ae11d006d944339..2c651eada6106fedad93297dec98b6238e295c03 100644 (file)
@@ -8,9 +8,34 @@
        Modifies .htaccess
 */
 $_YEAR = date('Y');
-$_PLANET_FOLDER = '<%= node[:planet][:dump][:xml_directory] %>/'.$_YEAR.'/';
-$_PLANET_REGEX = "/^(planet|changesets)\-\d{6}(\-nolt)?\.osm\.(bz2|gz)$/";
-$_MIRROR = 'https://ftp5.gwdg.de/pub/misc/openstreetmap/planet.openstreetmap.org/planet/'.$_YEAR.'/';
+
+$_MIRROR = 'https://ftp5.gwdg.de/pub/misc/openstreetmap/planet.openstreetmap.org/';
+
+$_FOLDERS = [
+              "planet_bz2" => [
+                          'FOLDER'     => '<%= node[:planet][:dump][:xml_directory] %>/'.$_YEAR.'/',
+                          'REGEX'      => '/^(planet|changesets|discussions)\-\d{6}(\-nolt)?\.osm\.(bz2|gz)$/',
+                          'DIR_PREFIX' => 'planet/'.$_YEAR.'/'
+                          ],
+
+              "history_bz2" => [
+                          'FOLDER' => '<%= node[:planet][:dump][:xml_history_directory] %>/'.$_YEAR.'/',
+                          'REGEX'  => '/^(history)\-\d{6}(\-nolt)?\.osm\.(bz2|gz)$/',
+                          'DIR_PREFIX' => 'planet/full-history/'.$_YEAR.'/'
+                          ],
+              "planet_pbf" => [
+                          'FOLDER'     => '<%= node[:planet][:dump][:pbf_directory] %>/',
+                          'REGEX'      => '/^(planet)\-\d{6}(\-nolt)?\.osm\.pbf$/',
+                          'DIR_PREFIX' => 'pbf/'
+                          ],
+
+              "history_pbf" => [
+                          'FOLDER' => '<%= node[:planet][:dump][:pbf_history_directory] %>/',
+                          'REGEX'  => '/^(history)\-\d{6}(\-nolt)?\.osm\.pbf$/',
+                          'DIR_PREFIX' => 'pbf/full-history/'
+                          ]
+            ];
+
 $_PLANET_HTACCESS = realpath('<%= node[:planet][:dump][:xml_directory] %>/..').'/.htaccess';
 
 function _MIRROR_FILE_SIZE($url) {
@@ -26,28 +51,36 @@ function _MIRROR_FILE_SIZE($url) {
 
 if (!is_writable($_PLANET_HTACCESS)) die('File '.$_PLANET_HTACCESS.' is not writable by current user.'."\n");
 
-if (is_dir($_PLANET_FOLDER)) {
-       $htaccess_contents = file_get_contents($_PLANET_HTACCESS);
-       $htaccess_handle = fopen($_PLANET_HTACCESS, 'a');
-       if ($dh = opendir($_PLANET_FOLDER)) {
-               while (($file = readdir($dh)) !== false ) {
-                       if (preg_match($_PLANET_REGEX,$file)) {
-                               $file_slashed = 'planet/'.$_YEAR.'/'.str_replace(array('.','-'), array('\.','\-'), $file);
-                               if (strpos($htaccess_contents,$file_slashed) === false) {
-                                       $file_size = filesize($_PLANET_FOLDER.$file);
-                                       sleep(rand(2,5));
-                                       $file_mirror_size = _MIRROR_FILE_SIZE($_MIRROR.$file);
-                                       if ($file_size==$file_mirror_size) {
-                                                       echo 'Adding: '.$file."\n";
-                                                       fwrite($htaccess_handle,        'RewriteRule'."\t".
-                                                                                       '^('.$file_slashed.')$'."\t".
-                                                                                       'https://ftp5.gwdg.de/pub/misc/openstreetmap/planet.openstreetmap.org/$1'."\t".
-                                                                                       '[R,L]'."\n");
-                                       }
-                               }
-                       }
-               }
-               closedir($dh);
-               fclose($htaccess_handle);
-       }
+$htaccess_contents = file_get_contents($_PLANET_HTACCESS);
+$htaccess_handle = fopen($_PLANET_HTACCESS, 'a');
+
+foreach ($_FOLDERS as $FOLDER) {
+
+  $_PLANET_FOLDER = $FOLDER["FOLDER"];
+  $_PLANET_REGEX  = $FOLDER["REGEX"];
+
+  if (!(is_dir($_PLANET_FOLDER))) {
+    continue;
+  }
+
+  if ($dh = opendir($_PLANET_FOLDER)) {
+    while (($file = readdir($dh)) !== false ) {
+      if (preg_match($_PLANET_REGEX, $file)) {
+        $file_slashed = str_replace(array('.','-'), array('\.','\-'), $FOLDER['DIR_PREFIX'].$file);
+        if (strpos($htaccess_contents, $file_slashed) === false) {
+          $file_size = filesize($_PLANET_FOLDER.$file);
+          sleep(rand(2,5));
+          $file_mirror_size = _MIRROR_FILE_SIZE($_MIRROR.$FOLDER['DIR_PREFIX'].$file);
+          if ($file_size==$file_mirror_size) {
+            echo 'Adding: '.$file."\n";
+            fwrite($htaccess_handle, 'RewriteRule'."\t". '^('.$file_slashed.')$'."\t".$_MIRROR.'$1'."\t".'[R,L]'."\n");
+          }
+        }
+      }
+    }
+    closedir($dh);
+  }
 }
+
+fclose($htaccess_handle);
+
diff --git a/cookbooks/planet/templates/default/planet-notes-dump.cron.erb b/cookbooks/planet/templates/default/planet-notes-dump.cron.erb
deleted file mode 100644 (file)
index 3c5709a..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-MAILTO=grant-smaug@firefishy.com
-0 3 * * * www-data /usr/local/bin/planet-notes-dump
-
-#Delete Planet Notes dump files older than 8 days
-10 8 * * * www-data find /store/planet/notes/20??/ -maxdepth 1 -type f -iname 'planet-notes-??????.osn*' -printf '\%T@ \%p\n' | sort -k 1nr | sed 's/^[^ ]* //' | tail -n +17 | xargs -r rm -f
index 92ca8b3758ec1313c4f366a515c14d77d5c8b105..77c73348f3755939a9d0ed9b15ea702b00f5b3cf 100644 (file)
@@ -33,7 +33,7 @@ if [ \! -d ${planet_dir}/notes/ ]
 if [ \! -d ${planet_dir}/notes/${cur_year}/ ]; then mkdir ${planet_dir}/notes/${cur_year}/; fi
 cd ${planet_dir}/notes/${cur_year}/
 
-/usr/bin/python /opt/planet-notes-dump/dump.py --quiet --database openstreetmap --host <%= node[:web][:readonly_database_host] %> --user planetdump --password '<%= @password %>' .${cur_planet_notes}
+/usr/bin/python3 /opt/planet-notes-dump/dump.py --quiet --database openstreetmap --host <%= node[:web][:readonly_database_host] %> --user planetdump --password '<%= @password %>' .${cur_planet_notes}
 pbzip2 -p6 -9 .${cur_planet_notes}
 
 planet_notes_size=$(du -sb .${cur_planet_notes}.bz2 | awk '{ print $1 }')
index 36786e23248fc360c9de3c7add158ad42f1b97d5..4b067e6401cf26bd505a381c7f33e89768e61498 100644 (file)
@@ -4,11 +4,13 @@
 
 # setup
 
+SUFFIX="osh.pbf"
+
 PLANETDIR="/var/lib/planet"
-PLANETPREV="${PLANETDIR}/planet-previous.pbf"
-PLANETCURR="${PLANETDIR}/planet.pbf"
-PLANETNEW="${PLANETDIR}/planet-new.pbf"
-PLANETTMP="${PLANETDIR}/planet-tmp.pbf"
+PLANETPREV="${PLANETDIR}/planet-previous.${SUFFIX}"
+PLANETCURR="${PLANETDIR}/planet.${SUFFIX}"
+PLANETNEW="${PLANETDIR}/planet-new.${SUFFIX}"
+PLANETTMP="${PLANETDIR}/planet-tmp.${SUFFIX}"
 
 pyosmium-up-to-date -v -o "$PLANETNEW" "$PLANETCURR"
 retval=$?
index 15a0051910152841cb635e898e8e7294b5e4d111..c6aca9423957548c26c7a816d5ad1a7798d22806 100644 (file)
@@ -67,12 +67,41 @@ rm -rf relations relation_tags relation_members
 
 # Run the dump
 time nice -n 19 /opt/planet-dump-ng/planet-dump-ng \
+     --max-concurrency=4 \
      -c "pbzip2 -c" -f "/store/backup/${file}" --dense-nodes=1 \
      -C "changesets-${date}.osm.bz2" \
      -D "discussions-${date}.osm.bz2" \
      -x "planet-${date}.osm.bz2" -X "history-${date}.osm.bz2" \
      -p "planet-${date}.osm.pbf" -P "history-${date}.osm.pbf"
 
+# Function to create bittorrent files
+function mk_torrent {
+  type="$1"
+  format="$2"
+  web_dir="$3"
+  name="${type}-${date}.osm.${format}"
+  web_path="${web_dir}/${name}"
+
+  mktorrent -l 22 ${name} \
+     -a udp://tracker.opentrackr.org:1337 \
+     -a udp://tracker.datacenterlight.ch:6969/announce,http://tracker.datacenterlight.ch:6969/announce \
+     -a udp://tracker.torrent.eu.org:451 \
+     -a udp://tracker-udp.gbitt.info:80/announce,http://tracker.gbitt.info/announce,https://tracker.gbitt.info/announce \
+     -a http://retracker.local/announce \
+     -w https://planet.openstreetmap.org/${web_path} \
+     -w https://ftp5.gwdg.de/pub/misc/openstreetmap/planet.openstreetmap.org/${web_path} \
+     -w https://ftpmirror.your.org/pub/openstreetmap/${web_path} \
+     -w https://mirror.init7.net/openstreetmap/${web_path} \
+     -w https://free.nchc.org.tw/osm.planet/${web_path} \
+     -w https://ftp.fau.de/osm-planet/${web_path} \
+     -w https://ftp.spline.de/pub/openstreetmap/${web_path} \
+     -w https://osm.openarchive.site/${name} \
+     -w https://downloads.opencagedata.com/planet/${name} \
+     -w https://planet.osm-hr.org/${web_path} \
+     -c "OpenStreetMap ${type} data export, licensed under https://opendatacommons.org/licenses/odbl/ by OpenStreetMap contributors" \
+     -o ${name}.torrent
+}
+
 # Function to install a dump in place
 function install_dump {
   type="$1"
@@ -86,10 +115,19 @@ function install_dump {
   mkdir -p "${dir}/${year}"
   mv "${name}" "${name}.md5" "${dir}/${year}"
   ln -sf "${year:-.}/${name}" "${dir}/${latest}"
+  test -f "${name}.torrent" && mv "${name}.torrent" "${dir}/${year}" && ln -sf "${year:-.}/${name}.torrent" "${dir}/${latest}.torrent"
   rm -f "${dir}/${latest}.md5"
   sed -e "s/${name}/${latest}/" "${dir}/${year}/${name}.md5" > "${dir}/${latest}.md5"
 }
 
+# Create *.torrent files
+mk_torrent "changesets" "bz2" "planet/${year}"
+mk_torrent "discussions" "bz2" "planet/${year}"
+mk_torrent "planet" "bz2" "planet/${year}"
+mk_torrent "history" "bz2" "planet/full-history/${year}"
+mk_torrent "planet" "pbf" "pbf"
+mk_torrent "history" "pbf" "pbf/full-history"
+
 # Move dumps into place
 install_dump "changesets" "bz2" "<%= node[:planet][:dump][:xml_directory] %>" "${year}"
 install_dump "discussions" "bz2" "<%= node[:planet][:dump][:xml_directory] %>" "${year}"
@@ -99,4 +137,12 @@ install_dump "planet" "pbf" "<%= node[:planet][:dump][:pbf_directory] %>"
 install_dump "history" "pbf" "<%= node[:planet][:dump][:pbf_history_directory] %>"
 
 # Remove pbf dumps older than 90 days
-find "<%= node[:planet][:dump][:pbf_directory] %>" "<%= node[:planet][:dump][:pbf_history_directory] %>" -maxdepth 1 -mindepth 1 -type f -mtime +90 \( -iname 'planet-*.pbf' -o -iname 'history-*.pbf' -o -iname 'planet-*.pbf.md5' -o -iname 'history-*.pbf.md5' \) -delete
+find "<%= node[:planet][:dump][:pbf_directory] %>" "<%= node[:planet][:dump][:pbf_history_directory] %>" \
+     -maxdepth 1 -mindepth 1 -type f -mtime +90 \
+     \( \
+     -iname 'planet-*.pbf' \
+     -o -iname 'history-*.pbf' \
+     -o -iname 'planet-*.pbf.md5' \
+     -o -iname 'history-*.pbf.md5' \
+     \) \
+     -delete
diff --git a/cookbooks/planet/templates/default/replicate-minute.erb b/cookbooks/planet/templates/default/replicate-minute.erb
new file mode 100644 (file)
index 0000000..a0c9671
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+set -e
+
+cd /etc/replication
+
+osmdbt-catchup --quiet
+osmdbt-get-log --quiet
+osmdbt-catchup --quiet
+osmdbt-create-diff --quiet --with-comment --max-changes=50000
diff --git a/cookbooks/planet/templates/default/replication.cron.erb b/cookbooks/planet/templates/default/replication.cron.erb
deleted file mode 100644 (file)
index 0ccffdd..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-
-TZ=UTC
-
-MAILTO=zerebubuth@gmail.com
-
-0 7 * * * planet /usr/local/bin/users-agreed
-0 17 * * * planet /usr/local/bin/users-deleted
-* * * * * planet /usr/local/bin/replicate-changesets /etc/replication/changesets.conf
-
-MAILTO=brett@bretth.com
-LD_PRELOAD=/opt/flush/flush.so
-
-* * * * * planet /usr/local/bin/osmosis -q --replicate-apidb authFile=/etc/replication/auth.conf validateSchemaVersion=false --write-replication workingDirectory=/store/planet/replication/minute
-2,7,12,17 * * * * planet /home/bretth/bin/osmosis -q --merge-replication-files workingDirectory=/var/lib/replication/hour
-5,10,15,20 * * * * planet /home/bretth/bin/osmosis -q --merge-replication-files workingDirectory=/var/lib/replication/day
diff --git a/cookbooks/planet/templates/default/streaming.init.erb b/cookbooks/planet/templates/default/streaming.init.erb
deleted file mode 100644 (file)
index 85ed3ef..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-start() {
-  start-stop-daemon --start --chuid planet --background --make-pidfile --pidfile /var/run/<%= @service %>.pid --exec /usr/local/bin/<%= @service %>
-}
-
-stop() {
-  start-stop-daemon --stop --retry 300 --pidfile /var/run/<%= @service %>.pid
-}
-
-status() {
-  start-stop-daemon --status --pidfile /var/run/<%= @service %>.pid
-}
-
-case "$1" in
-  start)
-    start
-    ;;
-  stop)
-    stop
-    ;;
-  restart)
-    stop || exit $?
-    start
-    ;;
-  status)
-    status
-    ;;
-esac
index dce61724fdf3ee97979813a2e3f26a9b1a8a44ed..770c0dbeacf1b3eccbf40e14ccf715318e055945 100644 (file)
@@ -1,13 +1,18 @@
 default[:postgresql][:versions] = []
 default[:postgresql][:clusters] = {}
+default[:postgresql][:monitor_tables] = true
 default[:postgresql][:settings][:defaults][:port] = "5432"
 default[:postgresql][:settings][:defaults][:max_connections] = "100"
+default[:postgresql][:settings][:defaults][:ssl] = "true"
 default[:postgresql][:settings][:defaults][:shared_buffers] = "32MB"
 default[:postgresql][:settings][:defaults][:temp_buffers] = "8MB"
 default[:postgresql][:settings][:defaults][:work_mem] = "1MB"
 default[:postgresql][:settings][:defaults][:maintenance_work_mem] = "16MB"
 default[:postgresql][:settings][:defaults][:max_stack_depth] = "2MB"
 default[:postgresql][:settings][:defaults][:effective_io_concurrency] = "1"
+default[:postgresql][:settings][:defaults][:max_worker_processes] = "8"
+default[:postgresql][:settings][:defaults][:max_parallel_workers_per_gather] = "2"
+default[:postgresql][:settings][:defaults][:max_parallel_workers] = "8"
 default[:postgresql][:settings][:defaults][:wal_level] = "minimal"
 default[:postgresql][:settings][:defaults][:fsync] = "on"
 default[:postgresql][:settings][:defaults][:synchronous_commit] = "on"
@@ -21,17 +26,28 @@ default[:postgresql][:settings][:defaults][:min_wal_size] = "80MB"
 default[:postgresql][:settings][:defaults][:checkpoint_completion_target] = "0.5"
 default[:postgresql][:settings][:defaults][:archive_mode] = "off"
 default[:postgresql][:settings][:defaults][:max_wal_senders] = "0"
+default[:postgresql][:settings][:defaults][:max_replication_slots] = "0"
 default[:postgresql][:settings][:defaults][:hot_standby] = "off"
 default[:postgresql][:settings][:defaults][:hot_standby_feedback] = "off"
 default[:postgresql][:settings][:defaults][:random_page_cost] = "4.0"
 default[:postgresql][:settings][:defaults][:cpu_tuple_cost] = "0.01"
 default[:postgresql][:settings][:defaults][:effective_cache_size] = "128MB"
+default[:postgresql][:settings][:defaults][:default_statistics_target] = "100"
+default[:postgresql][:settings][:defaults][:jit] = "on"
 default[:postgresql][:settings][:defaults][:log_min_duration_statement] = "-1"
 default[:postgresql][:settings][:defaults][:track_activity_query_size] = "1024"
+default[:postgresql][:settings][:defaults][:log_autovacuum_min_duration] = "-1"
 default[:postgresql][:settings][:defaults][:autovacuum_max_workers] = "3"
+default[:postgresql][:settings][:defaults][:autovacuum_naptime] = "1min"
 default[:postgresql][:settings][:defaults][:autovacuum_vacuum_scale_factor] = "0.2"
 default[:postgresql][:settings][:defaults][:autovacuum_analyze_scale_factor] = "0.1"
+default[:postgresql][:settings][:defaults][:autovacuum_freeze_max_age] = "200000000"
+default[:postgresql][:settings][:defaults][:autovacuum_multixact_freeze_max_age] = "400000000"
+default[:postgresql][:settings][:defaults][:shared_preload_libraries] = []
+default[:postgresql][:settings][:defaults][:max_locks_per_transaction] = "64"
 default[:postgresql][:settings][:defaults][:user_name_maps] = {}
 default[:postgresql][:settings][:defaults][:early_authentication_rules] = []
 default[:postgresql][:settings][:defaults][:late_authentication_rules] = []
 default[:postgresql][:settings][:defaults][:standby_mode] = "off"
+
+default[:apt][:sources] = node[:apt][:sources] | ["postgresql"]
index 47927729ea7b834fa8a051e40e6a84590c27a282..a145daf0e1794c967b9f236f25cc213153bf422f 100644 (file)
@@ -6,4 +6,7 @@ description       "Installs and configures postgresql"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "apt"
+depends           "munin"
 depends           "ohai"
+depends           "prometheus"
index 3a3c63de108fc2413aac45d60843255ace3a3fc8..47ec3e80bfffee64cc580f0b8e09747adc339fa6 100644 (file)
 # limitations under the License.
 #
 
+include_recipe "apt"
+include_recipe "munin"
+include_recipe "prometheus"
+
+package "locales-all"
 package "postgresql-common"
 
 node[:postgresql][:versions].each do |version|
@@ -32,7 +37,7 @@ node[:postgresql][:versions].each do |version|
     source "postgresql.conf.erb"
     owner "postgres"
     group "postgres"
-    mode 0o644
+    mode "644"
     variables :version => version, :defaults => defaults, :settings => settings
     notifies :reload, "service[postgresql]"
   end
@@ -41,7 +46,7 @@ node[:postgresql][:versions].each do |version|
     source "pg_hba.conf.erb"
     owner "postgres"
     group "postgres"
-    mode 0o640
+    mode "640"
     variables :early_rules => settings[:early_authentication_rules] || defaults[:early_authentication_rules],
               :late_rules => settings[:late_authentication_rules] || defaults[:late_authentication_rules]
     notifies :reload, "service[postgresql]"
@@ -51,7 +56,7 @@ node[:postgresql][:versions].each do |version|
     source "pg_ident.conf.erb"
     owner "postgres"
     group "postgres"
-    mode 0o640
+    mode "640"
     variables :maps => settings[:user_name_maps] || defaults[:user_name_maps]
     notifies :reload, "service[postgresql]"
   end
@@ -78,7 +83,7 @@ node[:postgresql][:versions].each do |version|
       source "recovery.conf.erb"
       owner "postgres"
       group "postgres"
-      mode 0o640
+      mode "640"
       variables :standby_mode => standby_mode,
                 :primary_conninfo => primary_conninfo,
                 :restore_command => restore_command,
@@ -102,7 +107,7 @@ ohai_plugin "postgresql" do
   template "ohai.rb.erb"
 end
 
-package "ptop"
+package "pgtop"
 package "libdbd-pg-perl"
 
 clusters = node[:postgresql][:clusters] || []
@@ -148,3 +153,24 @@ clusters.each do |name, details|
     conf_variables :port => details[:port]
   end
 end
+
+uris = clusters.collect do |_, details|
+  "postgres@:#{details[:port]}/postgres?host=/run/postgresql"
+end
+
+template "/etc/prometheus/exporters/postgres_queries.yml" do
+  source "postgres_queries.yml.erb"
+  owner "root"
+  group "root"
+  mode "644"
+end
+
+prometheus_exporter "postgres" do
+  port 9187
+  user "postgres"
+  options "--extend.query-path=/etc/prometheus/exporters/postgres_queries.yml"
+  environment "DATA_SOURCE_URI" => uris.sort.uniq.first,
+              "PG_EXPORTER_AUTO_DISCOVER_DATABASES" => "true",
+              "PG_EXPORTER_EXCLUDE_DATABASES" => "postgres,template0,template1"
+  subscribes :restart, "template[/etc/prometheus/exporters/postgres_queries.yml]"
+end
index 9cc4f1e0e39b75270c7ff1ca905a9f75601700cb..c73250464c99b35a865ed9f2da62b9d7ac6fe9a8 100644 (file)
@@ -19,9 +19,9 @@
 
 default_action :create
 
-property :database, :kind_of => String, :name_attribute => true
+property :database, :kind_of => String, :name_property => true
 property :cluster, :kind_of => String, :required => true
-property :owner, :kind_of => String, :required => true
+property :owner, :kind_of => String, :required => [:create]
 property :encoding, :kind_of => String, :default => "UTF8"
 property :collation, :kind_of => String, :default => "en_GB.UTF8"
 property :ctype, :kind_of => String, :default => "en_GB.UTF8"
index 8f59858b0c4389d033d7cf5e4379e25db3bd536b..3845546bcfd65630512c9d47829b7da6852bdc4f 100644 (file)
 
 default_action :run
 
-property :command, :kind_of => String, :name_attribute => true
+property :command, :kind_of => String, :name_property => true
 property :cluster, :kind_of => String, :required => true
 property :database, :kind_of => String, :required => true
-property :user, :default => "postgres"
-property :group, :default => "postgres"
-
-action :nothing do
-end
+property :user, :kind_of => String, :default => "postgres"
+property :group, :kind_of => String, :default => "postgres"
 
 action :run do
   options = { :database => new_resource.database, :user => new_resource.user, :group => new_resource.group }
index 24df6c568c46b39f0d6070c500c0fb4c11eecf50..3adcfd62b26761df9eb16869abb7ce93927e4a34 100644 (file)
@@ -19,7 +19,7 @@
 
 default_action :create
 
-property :extension, :kind_of => String, :name_attribute => true
+property :extension, :kind_of => String, :name_property => true
 property :cluster, :kind_of => String, :required => true
 property :database, :kind_of => String, :required => true
 
index e069a87723c3f173259d603dda5c33d6e4fffb67..311325b0f1b141a2cee6bb450e136cf0b782bfb5 100644 (file)
@@ -19,7 +19,7 @@
 
 default_action :create
 
-property :munin, :kind_of => String, :name_attribute => true
+property :munin, :kind_of => String, :name_property => true
 property :cluster, :kind_of => String, :required => true
 property :database, :kind_of => String, :required => true
 
index 75df2f60ca7c5f579590b0ede5e97aea49d98d4e..ed26559326cfbda1db84e665df8f2ddd76ababdf 100644 (file)
 
 default_action :create
 
-property :table, :kind_of => String, :name_attribute => true
+property :table, :kind_of => String, :name_property => true
 property :cluster, :kind_of => String, :required => true
 property :database, :kind_of => String, :required => true
 property :schema, :kind_of => String, :default => "public"
-property :owner, :kind_of => String, :required => true
+property :owner, :kind_of => String, :required => [:create]
 property :permissions, :kind_of => Hash, :default => {}
 
 action :create do
index 0fa05cafcf857da87827eb0f1678eee9a0524918..69e0ce2b0c508e68dbf2106f28e1f1ea0ca17b2f 100644 (file)
@@ -19,9 +19,9 @@
 
 default_action :create
 
-property :tablespace, :kind_of => String, :name_attribute => true
+property :tablespace, :kind_of => String, :name_property => true
 property :cluster, :kind_of => String, :required => true
-property :location, :kind_of => String, :required => true
+property :location, :kind_of => String, :required => [:create]
 
 action :create do
   unless cluster.tablespaces.include?(new_resource.tablespace)
index 072b18424700326d9165276369be2a1387e74547..ad8fed4d5f8e5047628e276cda344f6b30f58d45 100644 (file)
@@ -21,13 +21,13 @@ require "shellwords"
 
 default_action :create
 
-property :user, :kind_of => String, :name_attribute => true
+property :user, :kind_of => String, :name_property => true
 property :cluster, :kind_of => String, :required => true
 property :password, :kind_of => String
-property :superuser, :default => false
-property :createdb, :default => false
-property :createrole, :default => false
-property :replication, :default => false
+property :superuser, :kind_of => [TrueClass, FalseClass], :default => false
+property :createdb, :kind_of => [TrueClass, FalseClass], :default => false
+property :createrole, :kind_of => [TrueClass, FalseClass], :default => false
+property :replication, :kind_of => [TrueClass, FalseClass], :default => false
 
 action :create do
   password = new_resource.password ? "ENCRYPTED PASSWORD '#{new_resource.password.shellescape}'" : ""
diff --git a/cookbooks/postgresql/templates/default/postgres_queries.yml.erb b/cookbooks/postgresql/templates/default/postgres_queries.yml.erb
new file mode 100644 (file)
index 0000000..f513b33
--- /dev/null
@@ -0,0 +1,152 @@
+pg_replication:
+  query: "SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp())) AS lag_seconds"
+  master: true
+  metrics:
+    - lag_seconds:
+        usage: "GAUGE"
+        description: "Replication lag behind master in seconds"
+
+pg_postmaster:
+  query: "SELECT pg_postmaster_start_time as start_time_seconds from pg_postmaster_start_time()"
+  master: true
+  metrics:
+    - start_time_seconds:
+        usage: "GAUGE"
+        description: "Time at which postmaster started"
+<% if node[:postgresql][:monitor_tables] -%>
+
+pg_stat_user_tables:
+  query: "SELECT current_database() datname, schemaname, relname, seq_scan, seq_tup_read, idx_scan, idx_tup_fetch, n_tup_ins, n_tup_upd, n_tup_del, n_tup_hot_upd, n_live_tup, n_dead_tup, n_mod_since_analyze, COALESCE(last_vacuum, '1970-01-01Z'), COALESCE(last_vacuum, '1970-01-01Z') as last_vacuum, COALESCE(last_autovacuum, '1970-01-01Z') as last_autovacuum, COALESCE(last_analyze, '1970-01-01Z') as last_analyze, COALESCE(last_autoanalyze, '1970-01-01Z') as last_autoanalyze, vacuum_count, autovacuum_count, analyze_count, autoanalyze_count FROM pg_stat_user_tables"
+  metrics:
+    - datname:
+        usage: "LABEL"
+        description: "Name of current database"
+    - schemaname:
+        usage: "LABEL"
+        description: "Name of the schema that this table is in"
+    - relname:
+        usage: "LABEL"
+        description: "Name of this table"
+    - seq_scan:
+        usage: "COUNTER"
+        description: "Number of sequential scans initiated on this table"
+    - seq_tup_read:
+        usage: "COUNTER"
+        description: "Number of live rows fetched by sequential scans"
+    - idx_scan:
+        usage: "COUNTER"
+        description: "Number of index scans initiated on this table"
+    - idx_tup_fetch:
+        usage: "COUNTER"
+        description: "Number of live rows fetched by index scans"
+    - n_tup_ins:
+        usage: "COUNTER"
+        description: "Number of rows inserted"
+    - n_tup_upd:
+        usage: "COUNTER"
+        description: "Number of rows updated"
+    - n_tup_del:
+        usage: "COUNTER"
+        description: "Number of rows deleted"
+    - n_tup_hot_upd:
+        usage: "COUNTER"
+        description: "Number of rows HOT updated (i.e., with no separate index update required)"
+    - n_live_tup:
+        usage: "GAUGE"
+        description: "Estimated number of live rows"
+    - n_dead_tup:
+        usage: "GAUGE"
+        description: "Estimated number of dead rows"
+    - n_mod_since_analyze:
+        usage: "GAUGE"
+        description: "Estimated number of rows changed since last analyze"
+    - last_vacuum:
+        usage: "GAUGE"
+        description: "Last time at which this table was manually vacuumed (not counting VACUUM FULL)"
+    - last_autovacuum:
+        usage: "GAUGE"
+        description: "Last time at which this table was vacuumed by the autovacuum daemon"
+    - last_analyze:
+        usage: "GAUGE"
+        description: "Last time at which this table was manually analyzed"
+    - last_autoanalyze:
+        usage: "GAUGE"
+        description: "Last time at which this table was analyzed by the autovacuum daemon"
+    - vacuum_count:
+        usage: "COUNTER"
+        description: "Number of times this table has been manually vacuumed (not counting VACUUM FULL)"
+    - autovacuum_count:
+        usage: "COUNTER"
+        description: "Number of times this table has been vacuumed by the autovacuum daemon"
+    - analyze_count:
+        usage: "COUNTER"
+        description: "Number of times this table has been manually analyzed"
+    - autoanalyze_count:
+        usage: "COUNTER"
+        description: "Number of times this table has been analyzed by the autovacuum daemon"
+
+pg_statio_user_tables:
+  query: "SELECT current_database() datname, schemaname, relname, heap_blks_read, heap_blks_hit, idx_blks_read, idx_blks_hit, toast_blks_read, toast_blks_hit, tidx_blks_read, tidx_blks_hit FROM pg_statio_user_tables"
+  metrics:
+    - datname:
+        usage: "LABEL"
+        description: "Name of current database"
+    - schemaname:
+        usage: "LABEL"
+        description: "Name of the schema that this table is in"
+    - relname:
+        usage: "LABEL"
+        description: "Name of this table"
+    - heap_blks_read:
+        usage: "COUNTER"
+        description: "Number of disk blocks read from this table"
+    - heap_blks_hit:
+        usage: "COUNTER"
+        description: "Number of buffer hits in this table"
+    - idx_blks_read:
+        usage: "COUNTER"
+        description: "Number of disk blocks read from all indexes on this table"
+    - idx_blks_hit:
+        usage: "COUNTER"
+        description: "Number of buffer hits in all indexes on this table"
+    - toast_blks_read:
+        usage: "COUNTER"
+        description: "Number of disk blocks read from this table's TOAST table (if any)"
+    - toast_blks_hit:
+        usage: "COUNTER"
+        description: "Number of buffer hits in this table's TOAST table (if any)"
+    - tidx_blks_read:
+        usage: "COUNTER"
+        description: "Number of disk blocks read from this table's TOAST table indexes (if any)"
+    - tidx_blks_hit:
+        usage: "COUNTER"
+        description: "Number of buffer hits in this table's TOAST table indexes (if any)"
+<% end -%>
+
+pg_database:
+  query: "SELECT pg_database.oid AS datid, pg_database.datname, pg_database_size(pg_database.datname) AS size_bytes FROM pg_database"
+  master: true
+  cache_seconds: 30
+  metrics:
+    - datid:
+        usage: "LABEL"
+        description: "ID of the database"
+    - datname:
+        usage: "LABEL"
+        description: "Name of the database"
+    - size_bytes:
+        usage: "GAUGE"
+        description: "Disk space used by the database"
+
+pg_unfrozen_ids:
+  query: "SELECT current_database() AS datname, max(age(relfrozenxid)) AS xid_age, max(mxid_age(relminmxid)) AS mxid_age FROM pg_class WHERE relkind IN ('r', 'm')"
+  metrics:
+    - datname:
+        usage: "LABEL"
+        description: "Name of the database"
+    - xid_age:
+        usage: "GAUGE"
+        description: "Age of the oldest unfrozen transaction ID in this database"
+    - mxid_age:
+        usage: "GAUGE"
+        description: "Age of the oldest unfrozen multixact ID in this database"
index 6e9e29d6fb9a87ad6206f547e4390db6249428ea..d75c2f427a0fb44e567dbf8a75ee612c69b017a0 100644 (file)
@@ -28,7 +28,7 @@ unix_socket_directory = '/var/run/postgresql'
 
 # - Security and Authentication -
 
-ssl = true
+ssl = <%= @settings[:ssl] || @defaults[:ssl] %>
 ssl_renegotiation_limit = 0
 
 #------------------------------------------------------------------------------
@@ -46,6 +46,13 @@ max_stack_depth = <%= @settings[:max_stack_depth] || @defaults[:max_stack_depth]
 # - Asynchronous Behavior -
 
 effective_io_concurrency = <%= @settings[:effective_io_concurrency] || @defaults[:effective_io_concurrency] %>
+max_worker_processes = <%= @settings[:max_worker_processes] || @defaults[:max_worker_processes] %>
+<% if @version.to_f >= 9.6 -%>
+max_parallel_workers_per_gather = <%= @settings[:max_parallel_workers_per_gather] || @defaults[:max_parallel_workers_per_gather] %>
+<% end -%>
+<% if @version.to_f >= 10 -%>
+max_parallel_workers = <%= @settings[:max_parallel_workers] || @defaults[:max_parallel_workers] %>
+<% end -%>
 
 #------------------------------------------------------------------------------
 # WRITE AHEAD LOG
@@ -86,6 +93,9 @@ archive_command = '<%= @settings[:archive_command] || @defaults[:archive_command
 # - Sending Server(s) -
 
 max_wal_senders = <%= @settings[:max_wal_senders] || @defaults[:max_wal_senders] %>
+<% if @version.to_f >= 9.4 -%>
+max_replication_slots = <%= @settings[:max_replication_slots] || @defaults[:max_replication_slots] %>
+<% end -%>
 
 # - Standby Servers -
 
@@ -102,8 +112,15 @@ random_page_cost = <%= @settings[:random_page_cost] || @defaults[:random_page_co
 cpu_tuple_cost = <%= @settings[:cpu_tuple_cost] || @defaults[:cpu_tuple_cost] %>
 effective_cache_size = <%= @settings[:effective_cache_size] || @defaults[:effective_cache_size] %>
 
+# - Other Planner Options -
+
+default_statistics_target = <%= @settings[:default_statistics_target] || @defaults[:default_statistics_target] %>
+<% if @version.to_f >= 12 -%>
+jit = <%= @settings[:jit] || @defaults[:jit] %>
+<% end -%>
+
 #------------------------------------------------------------------------------
-# ERROR REPORTING AND LOGGING
+# REPORTING AND LOGGING
 #------------------------------------------------------------------------------
 
 # - When to Log -
@@ -121,14 +138,19 @@ log_line_prefix = '%t '
 # - Query/Index Statistics Collector -
 
 track_activity_query_size = <%= @settings[:track_activity_query_size] || @defaults[:track_activity_query_size] %>
+stats_temp_directory = '/run/postgresql/<%= @version %>-main.pg_stat_tmp'
 
 #------------------------------------------------------------------------------
 # AUTOVACUUM PARAMETERS
 #------------------------------------------------------------------------------
 
+log_autovacuum_min_duration = <%= @settings[:log_autovacuum_min_duration] || @defaults[:log_autovacuum_min_duration] %>
 autovacuum_max_workers = <%= @settings[:autovacuum_max_workers] || @defaults[:autovacuum_max_workers] %>
+autovacuum_naptime = <%= @settings[:autovacuum_naptime] || @defaults[:autovacuum_naptime] %>
 autovacuum_vacuum_scale_factor = <%= @settings[:autovacuum_vacuum_scale_factor] || @defaults[:autovacuum_vacuum_scale_factor] %>
 autovacuum_analyze_scale_factor = <%= @settings[:autovacuum_analyze_scale_factor] || @defaults[:autovacuum_analyze_scale_factor] %>
+autovacuum_freeze_max_age = <%= @settings[:autovacuum_freeze_max_age] || @defaults[:autovacuum_freeze_max_age] %>
+autovacuum_multixact_freeze_max_age = <%= @settings[:autovacuum_multixact_freeze_max_age] || @defaults[:autovacuum_multixact_freeze_max_age] %>
 
 #------------------------------------------------------------------------------
 # CLIENT CONNECTION DEFAULTS
@@ -142,3 +164,21 @@ lc_monetary = 'en_GB.UTF-8'
 lc_numeric = 'en_GB.UTF-8'
 lc_time = 'en_GB.UTF-8'
 default_text_search_config = 'pg_catalog.english'
+
+# - Shared Library Preloading -
+
+shared_preload_libraries = '<%= (@settings[:shared_preload_libraries] || @defaults[:shared_preload_libraries]).sort.join(",") %>'
+
+#------------------------------------------------------------------------------
+# LOCK MANAGEMENT
+#------------------------------------------------------------------------------
+
+max_locks_per_transaction = <%= @settings[:max_locks_per_transaction] || @defaults[:max_locks_per_transaction] %>
+
+#------------------------------------------------------------------------------
+# CUSTOMIZED OPTIONS
+#------------------------------------------------------------------------------
+
+<% Hash(@settings[:customized_options]).sort.each do |name, value| -%>
+<%= name %> = <%= value %>
+<% end -%>
diff --git a/cookbooks/prometheus/README.md b/cookbooks/prometheus/README.md
new file mode 100644 (file)
index 0000000..25feafa
--- /dev/null
@@ -0,0 +1,12 @@
+# Prometheus Cookbook
+
+This cookbook configures prometheus, which we use for server monitoring at
+[prometheus.openstreetmap.org](https://prometheus.openstreetmap.org). The
+cookbook contains two recipes:
+
+* default - installs and configures basic prometheus exporters on each machine
+* server - configures the central prometheus server
+
+Additionally two providers are defined - prometheus_exporter and
+prometheus_textfile_exporter, for configuring individual prometheus
+exporters.
diff --git a/cookbooks/prometheus/attributes/default.rb b/cookbooks/prometheus/attributes/default.rb
new file mode 100644 (file)
index 0000000..0200e1c
--- /dev/null
@@ -0,0 +1,7 @@
+default[:prometheus][:addresses] = {}
+default[:prometheus][:exporters] = {}
+default[:prometheus][:snmp] = {}
+
+if node[:recipes].include?("prometheus::server")
+  default[:apt][:sources] |= ["grafana"]
+end
diff --git a/cookbooks/prometheus/metadata.rb b/cookbooks/prometheus/metadata.rb
new file mode 100644 (file)
index 0000000..0d63556
--- /dev/null
@@ -0,0 +1,14 @@
+name              "prometheus"
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache-2.0"
+description       "Installs and configures prometheus"
+
+version           "1.0.0"
+supports          "ubuntu"
+depends           "apache"
+depends           "apt"
+depends           "git"
+depends           "hardware"
+depends           "networking"
+depends           "timescaledb"
diff --git a/cookbooks/prometheus/recipes/default.rb b/cookbooks/prometheus/recipes/default.rb
new file mode 100644 (file)
index 0000000..6e88362
--- /dev/null
@@ -0,0 +1,123 @@
+#
+# Cookbook:: prometheus
+# Recipe:: default
+#
+# Copyright:: 2020, OpenStreetMap Foundation
+#
+# 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
+#
+#     https://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.
+#
+
+include_recipe "git"
+include_recipe "networking"
+
+package "ruby"
+
+if node.internal_ipaddress
+  node.default[:prometheus][:mode] = "internal"
+  node.default[:prometheus][:address] = node.internal_ipaddress
+elsif node[:networking][:wireguard][:enabled]
+  node.default[:prometheus][:mode] = "wireguard"
+  node.default[:prometheus][:address] = node[:networking][:wireguard][:address]
+
+  search(:node, "roles:prometheus") do |server|
+    node.default[:networking][:wireguard][:peers] << {
+      :public_key => server[:networking][:wireguard][:public_key],
+      :allowed_ips => server[:networking][:wireguard][:address],
+      :endpoint => "#{server.name}:51820"
+    }
+  end
+else
+  node.default[:prometheus][:mode] = "external"
+  node.default[:prometheus][:address] = node.external_ipaddress(:family => :inet)
+end
+
+directory "/opt/prometheus" do
+  action :delete
+  owner "root"
+  group "root"
+  mode "755"
+  recursive true
+  not_if { ::Dir.exist?("/opt/prometheus/.git") }
+end
+
+git "/opt/prometheus" do
+  action :sync
+  repository "https://github.com/openstreetmap/prometheus-exporters.git"
+  revision "main"
+  depth 1
+  user "root"
+  group "root"
+end
+
+directory "/etc/prometheus/collectors" do
+  owner "root"
+  group "root"
+  mode "755"
+  recursive true
+end
+
+directory "/etc/prometheus/exporters" do
+  owner "root"
+  group "root"
+  mode "755"
+  recursive true
+end
+
+directory "/var/lib/prometheus/node-exporter" do
+  owner "root"
+  group "adm"
+  mode "775"
+  recursive true
+end
+
+template "/var/lib/prometheus/node-exporter/chef.prom" do
+  source "chef.prom.erb"
+  owner "root"
+  group "root"
+  mode "644"
+end
+
+metric_relabel = []
+
+node[:hardware][:hwmon].each do |chip, details|
+  next unless details[:ignore]
+
+  sensors = details[:ignore].join("|")
+
+  metric_relabel << {
+    :source_labels => "chip,sensor",
+    :regex => "#{chip};(#{sensors})",
+    :action => "drop"
+  }
+end
+
+prometheus_exporter "node" do
+  port 9100
+  options %w[
+    --collector.textfile.directory=/var/lib/prometheus/node-exporter
+    --collector.interrupts
+    --collector.ntp
+    --collector.processes
+    --collector.systemd
+    --collector.tcpstat
+  ]
+  metric_relabel metric_relabel
+end
+
+unless node[:prometheus][:snmp].empty?
+  prometheus_exporter "snmp" do
+    port 9116
+    options "--config.file=/opt/prometheus/exporters/snmp/snmp.yml"
+    register_target false
+  end
+end
diff --git a/cookbooks/prometheus/recipes/server.rb b/cookbooks/prometheus/recipes/server.rb
new file mode 100644 (file)
index 0000000..382fc7f
--- /dev/null
@@ -0,0 +1,308 @@
+#
+# Cookbook:: prometheus
+# Recipe:: server
+#
+# Copyright:: 2020, OpenStreetMap Foundation
+#
+# 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
+#
+#     https://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.
+#
+
+include_recipe "apache"
+include_recipe "apt"
+include_recipe "networking"
+include_recipe "timescaledb"
+
+passwords = data_bag_item("prometheus", "passwords")
+tokens = data_bag_item("prometheus", "tokens")
+
+prometheus_exporter "fastly" do
+  port 8080
+  listen_switch "endpoint"
+  listen_type "url"
+  environment "FASTLY_API_TOKEN" => tokens["fastly"]
+end
+
+package %w[
+  prometheus
+  prometheus-alertmanager
+]
+
+promscale_version = "0.2.0"
+
+database_cluster = "#{node[:timescaledb][:database_version]}/main"
+
+postgresql_user "prometheus" do
+  cluster database_cluster
+  superuser true
+end
+
+postgresql_database "promscale" do
+  cluster database_cluster
+  owner "prometheus"
+end
+
+directory "/opt/promscale" do
+  owner "root"
+  group "root"
+  mode "755"
+end
+
+package %w[
+  make
+  gcc
+  clang-9
+  llvm-9
+  cargo
+]
+
+git "/opt/promscale/extension" do
+  action :sync
+  repository "https://github.com/timescale/promscale_extension.git"
+  revision "0.1.1"
+  user "root"
+  group "root"
+end
+
+execute "/opt/promscale/extension/Makefile" do
+  action :nothing
+  command "make install"
+  cwd "/opt/promscale/extension"
+  user "root"
+  group "root"
+  subscribes :run, "git[/opt/promscale/extension]", :immediately
+  notifies :restart, "service[postgresql]", :immediately
+end
+
+directory "/opt/promscale/bin" do
+  owner "root"
+  group "root"
+  mode "755"
+end
+
+remote_file "/opt/promscale/bin/promscale" do
+  action :create
+  source "https://github.com/timescale/promscale/releases/download/#{promscale_version}/promscale_#{promscale_version}_Linux_x86_64"
+  owner "root"
+  group "root"
+  mode "755"
+end
+
+systemd_service "promscale" do
+  description "Promscale Connector"
+  type "simple"
+  user "prometheus"
+  exec_start "/opt/promscale/bin/promscale --db-host /run/postgresql --db-port 5432 --db-user prometheus --db-name promscale --db-connections-max 400"
+  # exec_start lazy { "/opt/promscale/bin/promscale --db-host /run/postgresql --db-port #{node[:postgresql][:clusters][database_cluster][:port]} --db-user prometheus --db-name promscale --db-max-connections 400" }
+  limit_nofile 16384
+  private_tmp true
+  protect_system "strict"
+  protect_home true
+  no_new_privileges true
+end
+
+service "promscale" do
+  action [:enable, :start]
+  subscribes :restart, "remote_file[/opt/promscale/bin/promscale]"
+  subscribes :restart, "systemd_service[promscale]"
+end
+
+systemd_service "promscale-maintenance" do
+  description "Promscale Maintenace"
+  type "simple"
+  user "prometheus"
+  exec_start "/usr/bin/psql --command='CALL prom_api.execute_maintenance()' promscale"
+  private_tmp true
+  protect_system "strict"
+  protect_home true
+  no_new_privileges true
+end
+
+systemd_timer "promscale-maintenance" do
+  description "Promscale Maintenace"
+  on_active_sec 1800
+  on_unit_inactive_sec 1800
+end
+
+service "promscale-maintenance.timer" do
+  action [:enable, :start]
+end
+
+search(:node, "roles:gateway") do |gateway|
+  allowed_ips = gateway.interfaces(:role => :internal).map do |interface|
+    "#{interface[:network]}/#{interface[:prefix]}"
+  end
+
+  node.default[:networking][:wireguard][:peers] << {
+    :public_key => gateway[:networking][:wireguard][:public_key],
+    :allowed_ips => allowed_ips,
+    :endpoint => "#{gateway.name}:51820"
+  }
+end
+
+jobs = {}
+snmp_targets = []
+
+search(:node, "recipes:prometheus\\:\\:default").sort_by(&:name).each do |client|
+  if client[:prometheus][:mode] == "wireguard"
+    node.default[:networking][:wireguard][:peers] << {
+      :public_key => client[:networking][:wireguard][:public_key],
+      :allowed_ips => client[:networking][:wireguard][:address],
+      :endpoint => "#{client.name}:51820"
+    }
+  end
+
+  client[:prometheus][:exporters].each do |key, exporter|
+    if exporter.is_a?(Hash)
+      name = exporter[:name]
+      address = exporter[:address]
+      metric_relabel = exporter[:metric_relabel] || []
+    else
+      name = key
+      address = exporter
+      metric_relabel = []
+    end
+
+    jobs[name] ||= []
+    jobs[name] << {
+      :address => address,
+      :instance => client.name.split(".").first,
+      :metric_relabel => metric_relabel
+    }
+  end
+
+  Hash(client[:prometheus][:snmp]).each do |instance, details|
+    snmp_targets << {
+      :instance => instance,
+      :target => details[:address],
+      :module => details[:module],
+      :address => client[:prometheus][:addresses]["snmp"],
+      :labels => Array(details[:labels])
+    }
+  end
+end
+
+certificates = search(:node, "letsencrypt:certificates").each_with_object({}) do |n, c|
+  n[:letsencrypt][:certificates].each do |name, details|
+    c[name] ||= details.merge(:nodes => [])
+
+    c[name][:nodes] << {
+      :name => n[:fqdn],
+      :address => n.external_ipaddress || n.internal_ipaddress
+    }
+  end
+end
+
+template "/etc/prometheus/ssl.yml" do
+  source "ssl.yml.erb"
+  owner "root"
+  group "root"
+  mode "644"
+  variables :certificates => certificates
+end
+
+prometheus_exporter "ssl" do
+  address "127.0.0.1"
+  port 9219
+  options "--config.file=/etc/prometheus/ssl.yml"
+  register_target false
+end
+
+template "/etc/default/prometheus" do
+  source "default.prometheus.erb"
+  owner "root"
+  group "root"
+  mode "644"
+end
+
+template "/etc/prometheus/prometheus.yml" do
+  source "prometheus.yml.erb"
+  owner "root"
+  group "root"
+  mode "644"
+  variables :jobs => jobs, :snmp_targets => snmp_targets, :certificates => certificates
+end
+
+template "/etc/prometheus/alert_rules.yml" do
+  source "alert_rules.yml.erb"
+  owner "root"
+  group "root"
+  mode "644"
+end
+
+service "prometheus" do
+  action [:enable, :start]
+  subscribes :restart, "template[/etc/default/prometheus]"
+  subscribes :reload, "template[/etc/prometheus/prometheus.yml]"
+  subscribes :reload, "template[/etc/prometheus/alert_rules.yml]"
+end
+
+template "/etc/default/prometheus-alertmanager" do
+  source "default.alertmanager.erb"
+  owner "root"
+  group "root"
+  mode "644"
+end
+
+template "/etc/prometheus/alertmanager.yml" do
+  source "alertmanager.yml.erb"
+  owner "root"
+  group "root"
+  mode "644"
+end
+
+service "prometheus-alertmanager" do
+  action [:enable, :start]
+  subscribes :restart, "template[/etc/default/prometheus-alertmanager]"
+  subscribes :reload, "template[/etc/prometheus/alertmanager.yml]"
+end
+
+template "/etc/prometheus/amtool.yml" do
+  source "amtool.yml.erb"
+  owner "root"
+  group "root"
+  mode "644"
+end
+
+package "grafana-enterprise"
+
+template "/etc/grafana/grafana.ini" do
+  source "grafana.ini.erb"
+  owner "root"
+  group "grafana"
+  mode "640"
+  variables :passwords => passwords
+end
+
+service "grafana-server" do
+  action [:enable, :start]
+  subscribes :restart, "template[/etc/grafana/grafana.ini]"
+end
+
+apache_module "alias"
+apache_module "proxy_http"
+
+ssl_certificate "prometheus.openstreetmap.org" do
+  domains ["prometheus.openstreetmap.org", "prometheus.osm.org"]
+  notifies :reload, "service[apache2]"
+end
+
+apache_site "prometheus.openstreetmap.org" do
+  template "apache.erb"
+end
+
+template "/etc/cron.daily/prometheus-backup" do
+  source "backup.cron.erb"
+  owner "root"
+  group "root"
+  mode "750"
+end
diff --git a/cookbooks/prometheus/resources/collector.rb b/cookbooks/prometheus/resources/collector.rb
new file mode 100644 (file)
index 0000000..c9c28fc
--- /dev/null
@@ -0,0 +1,85 @@
+#
+# Cookbook:: prometheus
+# Resource:: prometheus_collector
+#
+# Copyright:: 2020, OpenStreetMap Foundation
+#
+# 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
+#
+#     https://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.
+#
+
+default_action :create
+
+property :collector, :kind_of => String, :name_property => true
+property :interval, :kind_of => [Integer, String], :required => [:create]
+property :options, :kind_of => [String, Array]
+property :environment, :kind_of => Hash, :default => {}
+
+action :create do
+  systemd_service service_name do
+    description "Prometheus #{new_resource.collector} collector"
+    user "root"
+    environment new_resource.environment
+    standard_output "file:/var/lib/prometheus/node-exporter/#{new_resource.collector}.new"
+    standard_error "journal"
+    exec_start "#{executable_path} #{executable_options}"
+    exec_start_post "/bin/mv /var/lib/prometheus/node-exporter/#{new_resource.collector}.new /var/lib/prometheus/node-exporter/#{new_resource.collector}.prom"
+    private_tmp true
+    protect_system "strict"
+    protect_home true
+    read_write_paths "/var/lib/prometheus/node-exporter"
+    no_new_privileges true
+  end
+
+  systemd_timer service_name do
+    description "Prometheus #{new_resource.collector} collector"
+    on_boot_sec 60
+    on_unit_active_sec new_resource.interval
+  end
+
+  service "#{service_name}.timer" do
+    action [:enable, :start]
+    subscribes :restart, "systemd_timer[#{service_name}]"
+  end
+end
+
+action :delete do
+  service "#{service_name}.timer" do
+    action [:disable, :stop]
+  end
+
+  systemd_timer service_name do
+    action :delete
+  end
+
+  systemd_service service_name do
+    action :delete
+  end
+
+  file "/var/lib/prometheus/node-exporter/#{new_resource.collector}.prom" do
+    action :delete
+  end
+end
+
+action_class do
+  def service_name
+    "prometheus-#{new_resource.collector}-collector"
+  end
+
+  def executable_path
+    "/opt/prometheus/collectors/#{new_resource.collector}/#{new_resource.collector}_collector"
+  end
+
+  def executable_options
+    Array(new_resource.options).join(" ")
+  end
+end
diff --git a/cookbooks/prometheus/resources/exporter.rb b/cookbooks/prometheus/resources/exporter.rb
new file mode 100644 (file)
index 0000000..bab318a
--- /dev/null
@@ -0,0 +1,126 @@
+#
+# Cookbook:: prometheus
+# Resource:: prometheus_exporter
+#
+# Copyright:: 2020, OpenStreetMap Foundation
+#
+# 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
+#
+#     https://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.
+#
+
+default_action :create
+
+property :exporter, :kind_of => String, :name_property => true
+property :address, :kind_of => String
+property :port, :kind_of => Integer, :required => [:create]
+property :listen_switch, :kind_of => String, :default => "web.listen-address"
+property :listen_type, :kind_of => String, :default => "address"
+property :user, :kind_of => String, :default => "root"
+property :command, :kind_of => String
+property :options, :kind_of => [String, Array]
+property :environment, :kind_of => Hash, :default => {}
+property :service, :kind_of => String
+property :metric_relabel, :kind_of => Array
+property :register_target, :kind_of => [TrueClass, FalseClass], :default => true
+
+action :create do
+  systemd_service service_name do
+    description "Prometheus #{new_resource.exporter} exporter"
+    type "simple"
+    user new_resource.user
+    environment new_resource.environment
+    exec_start "#{executable_path} #{new_resource.command} #{executable_options}"
+    private_tmp true
+    protect_system "strict"
+    protect_home true
+    no_new_privileges true
+  end
+
+  service service_name do
+    action [:enable, :start]
+    subscribes :restart, "systemd_service[#{service_name}]"
+  end
+
+  firewall_rule "accept-prometheus-#{new_resource.exporter}" do
+    action :accept
+    source "osm"
+    dest "fw"
+    proto "tcp:syn"
+    dest_ports new_resource.port
+    only_if { node[:prometheus][:mode] == "external" }
+  end
+
+  node.default[:prometheus][:addresses][new_resource.exporter] = listen_address
+
+  if new_resource.register_target
+    node.default[:prometheus][:exporters][new_resource.port] = {
+      :name => new_resource.exporter,
+      :address => listen_address,
+      :metric_relabel => new_resource.metric_relabel
+    }
+  end
+end
+
+action :delete do
+  service service_name do
+    action [:disable, :stop]
+  end
+
+  systemd_service service_name do
+    action :delete
+  end
+end
+
+action :restart do
+  service service_name do
+    action :restart
+  end
+end
+
+action_class do
+  def service_name
+    if new_resource.service
+      "prometheus-#{new_resource.service}-exporter"
+    else
+      "prometheus-#{new_resource.exporter}-exporter"
+    end
+  end
+
+  def executable_path
+    "/opt/prometheus/exporters/#{new_resource.exporter}/#{new_resource.exporter}_exporter"
+  end
+
+  def executable_options
+    "--#{new_resource.listen_switch}=#{listen_argument} #{Array(new_resource.options).join(' ')}"
+  end
+
+  def listen_argument
+    case new_resource.listen_type
+    when "address" then listen_address
+    when "url" then "http://#{listen_address}/metrics"
+    end
+  end
+
+  def listen_address
+    if new_resource.address
+      "#{new_resource.address}:#{new_resource.port}"
+    elsif node[:prometheus][:mode] == "wireguard"
+      "[#{node[:prometheus][:address]}]:#{new_resource.port}"
+    else
+      "#{node[:prometheus][:address]}:#{new_resource.port}"
+    end
+  end
+end
+
+def after_created
+  subscribes :restart, "git[/opt/prometheus]"
+end
diff --git a/cookbooks/prometheus/templates/default/alert_rules.yml.erb b/cookbooks/prometheus/templates/default/alert_rules.yml.erb
new file mode 100644 (file)
index 0000000..fd25f25
--- /dev/null
@@ -0,0 +1,260 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+groups:
+  - name: alertmanager
+    rules:
+      - alert: prometheus target missing
+        expr: up == 0
+        for: 5m
+        labels:
+          alertgroup: "prometheus"
+  - name: apache
+    rules:
+      - alert: apache down
+        expr: apache_up == 0
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+      - alert: apache workers busy
+        expr: sum(apache_workers{state="busy"}) by (instance) / sum(apache_scoreboard) by (instance) > 0.8
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          busy_workers: "{{ $value | humanizePercentage }}"
+  - name: database
+    rules:
+      - alert: postgres replication delay
+        expr: pg_replication_lag_seconds > 5
+        for: 5m
+        labels:
+          alertgroup: database
+        annotations:
+          delay: "{{ $value | humanizeDuration }}"
+  - name: hwmon
+    rules:
+      - alert: hwmon fan alarm
+        expr: node_hwmon_fan_alarm == 1
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          fan_rpm: "{{ with printf \"node_hwmon_fan_rpm{instance='%s',chip='%s',sensor='%s'}\" $labels.instance $labels.chip $labels.sensor | query }}{{ . | first | value | humanize }}rpm{{end}}"
+          fan_min_rpm: "{{ with printf \"node_hwmon_fan_min_rpm{instance='%s',chip='%s',sensor='%s'}\" $labels.instance $labels.chip $labels.sensor | query }}{{ . | first | value | humanize }}rpm{{end}}"
+      - alert: hwmon temperature alarm
+        expr: node_hwmon_temp_alarm == 1
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          temp_celsius: "{{ with printf \"node_hwmon_temp_celsius{instance='%s',chip='%s',sensor='%s'}\" $labels.instance $labels.chip $labels.sensor | query }}{{ . | first | value | humanize }}C{{end}}"
+          temp_max_celsius: "{{ with printf \"node_hwmon_temp_max_celsius{instance='%s',chip='%s',sensor='%s'}\" $labels.instance $labels.chip $labels.sensor | query }}{{ . | first | value | humanize }}C{{end}}"
+          temp_crit_celsius: "{{ with printf \"node_hwmon_temp_crit_celsius{instance='%s',chip='%s',sensor='%s'}\" $labels.instance $labels.chip $labels.sensor | query }}{{ . | first | value | humanize }}C{{end}}"
+      - alert: hwmon voltage alarm
+        expr: node_hwmon_in_alarm == 1
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          in_volts: "{{ with printf \"node_hwmon_in_volts{instance='%s',chip='%s',sensor='%s'}\" $labels.instance $labels.chip $labels.sensor | query }}{{ . | first | value | humanize }}V{{end}}"
+          in_min_volts: "{{ with printf \"node_hwmon_in_min_volts{instance='%s',chip='%s',sensor='%s'}\" $labels.instance $labels.chip $labels.sensor | query }}{{ . | first | value | humanize }}V{{end}}"
+          in_max_volts: "{{ with printf \"node_hwmon_in_max_volts{instance='%s',chip='%s',sensor='%s'}\" $labels.instance $labels.chip $labels.sensor | query }}{{ . | first | value | humanize }}V{{end}}"
+  - name: ipmi
+    rules:
+      - alert: ipmi fan alarm
+        expr: ipmi_fan_speed_state > 0
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          fan_speed_rpm: "{{ with printf \"ipmi_fan_speed_rpm{instance='%s',id='%s'}\" $labels.instance $labels.id | query }}{{ . | first | value | humanize }}rpm{{end}}"
+      - alert: ipmi temperature alarm
+        expr: ipmi_temperature_state > 0
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          temperature_celsius: "{{ with printf \"ipmi_temperature_celsius{instance='%s',id='%s'}\" $labels.instance $labels.id | query }}{{ . | first | value | humanize }}C{{end}}"
+      - alert: ipmi voltage alarm
+        expr: ipmi_voltage_state > 0
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          voltage_volts: "{{ with printf \"ipmi_voltage_volts{instance='%s',id='%s'}\" $labels.instance $labels.id | query }}{{ . | first | value | humanize }}V{{end}}"
+      - alert: ipmi power alarm
+        expr: ipmi_power_state > 0 or ipmi_sensor_state{type=~"Power .*"} > 0
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+  - name: mdadm
+    rules:
+      - alert: mdadm array inactive
+        expr: node_md_state{state="inactive"} > 0
+        for: 0m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          required: "{{ with printf \"node_md_disks_required{instance='%s',device='%s'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
+          active: "{{ with printf \"node_md_disks{instance='%s',device='%s',state='active'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
+          failed: "{{ with printf \"node_md_disks{instance='%s',device='%s',state='failed'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
+          spare: "{{ with printf \"node_md_disks{instance='%s',device='%s',state='spare'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
+      - alert: mdadm disk failed
+        expr: node_md_disks{state="failed"} > 0
+        for: 0m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          required: "{{ with printf \"node_md_disks_required{instance='%s',device='%s'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
+          active: "{{ with printf \"node_md_disks{instance='%s',device='%s',state='active'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
+          failed: "{{ with printf \"node_md_disks{instance='%s',device='%s',state='failed'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
+          spare: "{{ with printf \"node_md_disks{instance='%s',device='%s',state='spare'}\" $labels.instance $labels.device | query }}{{ . | first | value | humanize }} disks{{end}}"
+  - name: memory
+    rules:
+      - alert: low memory
+        expr: node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes < 0.1
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          memory_free: "{{ $value | humanizePercentage }}"
+      - alert: memory pressure
+        expr: rate(node_vmstat_pgmajfault[1m]) > 1000
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          major_page_faults: "{{ $value }} faults/s"
+      - alert: oom kill detected
+        expr: increase(node_vmstat_oom_kill[1m]) > 0
+        for: 0m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          new_oom_kills: "{{ $value }}"
+  - name: network
+    rules:
+      - alert: interface transmit rate
+        expr: rate(node_network_transmit_bytes_total[1m]) / node_network_speed_bytes > 0.98
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          bandwidth_used: "{{ $value | humanizePercentage }}"
+      - alert: interface receive rate
+        expr: rate(node_network_receive_bytes_total[1m]) / node_network_speed_bytes > 0.98
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          bandwidth_used: "{{ $value | humanizePercentage }}"
+      - alert: interface transmit errors
+        expr: rate(node_network_transmit_errs_total[1m]) / rate(node_network_transmit_packets_total[1m]) > 0.01
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          error_rate: "{{ $value | humanizePercentage }}"
+      - alert: interface receive errors
+        expr: rate(node_network_receive_errs_total[1m]) / rate(node_network_receive_packets_total[1m]) > 0.01
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          error_rate: "{{ $value | humanizePercentage }}"
+      - alert: conntrack entries
+        expr: node_nf_conntrack_entries / node_nf_conntrack_entries_limit > 0.8
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          entries_used: "{{ $value | humanizePercentage }}"
+  - name: postgresql
+    rules:
+      - alert: postgresql down
+        expr: pg_up == 0
+        for: 1m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+      - alert: postgresql replication delay
+        expr: pg_replication_lag_seconds > 5
+        for: 1m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          delay: "{{ $value | humanizeDuration }}"
+      - alert: postgresql connection limit
+        expr: sum (pg_stat_activity_count) by (instance, server) / sum (pg_settings_max_connections) by (instance, server) > 0.8
+        for: 1m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          connections_used: "{{ $value | humanizePercentage }}"
+      - alert: postgresql deadlocks
+        expr: increase(pg_stat_database_deadlocks[1m]) > 5
+        for: 0m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          new_deadlocks: "{{ $value }}"
+      - alert: postgresql slow queries
+        expr: pg_slow_queries > 0
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          queries: "{{ $value }}"
+  - name: ssl
+    rules:
+      - alert: ssl certificate probe failed
+        expr: ssl_probe_success == 0
+        for: 60m
+        labels:
+          alertgroup: ssl
+      - alert: ssl certificate expiry
+        expr: ssl_verified_cert_not_after{chain_no="0"} - time() < 86400 * 14
+        for: 0m
+        labels:
+          alertgroup: ssl
+        annotations:
+          expires_in: "{{ $value | humanizeDuration }}"
+      - alert: ssl certificate revoked
+        expr: ssl_ocsp_response_status == 1
+        for: 0m
+        labels:
+          alertgroup: ssl
+      - alert: ocsp status unknown
+        expr: ssl_ocsp_response_status == 1
+        for: 0m
+        labels:
+          alertgroup: ssl
+  - name: tile
+    rules:
+      - alert: renderd replication delay
+        expr: renderd_replication_delay > 120
+        for: 5m
+        labels:
+          alertgroup: tile
+        annotations:
+          delay: "{{ $value | humanizeDuration }}"
+      - alert: missed tile rate
+        expr: sum(rate(modtile_http_response_total{code="404"}[5m])) by (instance) / sum(rate(modtile_http_response_total[5m])) by (instance) > 0.05
+        for: 5m
+        labels:
+          alertgroup: tile
+        annotations:
+          miss_rate: "{{ $value | humanizePercentage }}"
+  - name: time
+    rules:
+      - alert: clock not synchronising
+        expr: min_over_time(node_timex_sync_status[1m]) == 0 and node_timex_maxerror_seconds >= 16
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+      - alert: clock skew detected
+        expr: (node_timex_offset_seconds > 0.05 and deriv(node_timex_offset_seconds[5m]) >= 0) or (node_timex_offset_seconds < -0.05 and deriv(node_timex_offset_seconds[5m]) <= 0)
+        for: 5m
+        labels:
+          alertgroup: "{{ $labels.instance }}"
+        annotations:
+          skew: "{{ with printf \"node_timex_offset_seconds{instance='%s'}\" $labels.instance | query }} {{ . | humanizeDuration }}{{ end }}"
diff --git a/cookbooks/prometheus/templates/default/alertmanager.yml.erb b/cookbooks/prometheus/templates/default/alertmanager.yml.erb
new file mode 100644 (file)
index 0000000..7433f99
--- /dev/null
@@ -0,0 +1,25 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+global:
+  smtp_smarthost: localhost:25
+  smtp_from: prometheus@openstreetmap.org
+  smtp_require_tls: false
+
+templates:
+  - /etc/prometheus/alertmanager_templates/*.tmpl
+
+route:
+  group_by:
+    - alertgroup
+  group_wait: 30s
+  group_interval: 5m
+  repeat_interval: 3h
+  receiver: admins-email
+
+inhibit_rules:
+
+receivers:
+  - name: admins-email
+    email_configs:
+      - send_resolved: true
+        to: admins@openstreetmap.org
similarity index 50%
rename from cookbooks/planet/templates/default/planet-update.cron.erb
rename to cookbooks/prometheus/templates/default/amtool.yml.erb
index 5a9f6f768158168208f58cc0ae0bb1f22c119da7..2bd46566138d6e1800e3f807b5175bce85d9057e 100644 (file)
@@ -1,3 +1,3 @@
 # DO NOT EDIT - This file is being maintained by Chef
 
-17 1 * * * root /usr/local/bin/planet-update
+alertmanager.url: http://localhost:9093/alertmanager
diff --git a/cookbooks/prometheus/templates/default/apache.erb b/cookbooks/prometheus/templates/default/apache.erb
new file mode 100644 (file)
index 0000000..00760ed
--- /dev/null
@@ -0,0 +1,31 @@
+# DO NOT EDIT - This file is being maintained by Prometheus
+
+<VirtualHost *:80>
+       ServerName prometheus.openstreetmap.org
+       ServerAlias prometheus.osm.org
+       ServerAdmin webmaster@openstreetmap.org
+
+       CustomLog /var/log/apache2/prometheus.openstreetmap.org-access.log combined
+       ErrorLog /var/log/apache2/prometheus.openstreetmap.org-error.log
+
+       RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
+       Redirect permanent / https://prometheus.openstreetmap.org/
+</VirtualHost>
+
+<VirtualHost *:443>
+       ServerName prometheus.openstreetmap.org
+       ServerAdmin webmaster@openstreetmap.org
+
+       CustomLog /var/log/apache2/prometheus.openstreetmap.org-access.log combined
+       ErrorLog /var/log/apache2/prometheus.openstreetmap.org-error.log
+
+       SSLEngine on
+       SSLCertificateFile /etc/ssl/certs/prometheus.openstreetmap.org.pem
+       SSLCertificateKeyFile /etc/ssl/private/prometheus.openstreetmap.org.key
+
+       ProxyPass /prometheus http://localhost:9090/prometheus
+       Redirect 403 /alertmanager/api
+       ProxyPass /alertmanager http://localhost:9093/alertmanager
+       ProxyPass / http://localhost:3000/
+       ProxyPreserveHost on
+</VirtualHost>
diff --git a/cookbooks/prometheus/templates/default/backup.cron.erb b/cookbooks/prometheus/templates/default/backup.cron.erb
new file mode 100644 (file)
index 0000000..3273aac
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+T=$(mktemp -d -t -p /var/tmp prometheus.XXXXXXXXXX)
+D=$(date +%Y-%m-%d)
+B=prometheus-$D.tar.gz
+
+mkdir $T/prometheus-$D
+
+ln -s /var/lib/prometheus/alertmanager $T/prometheus-$D/alertmanager
+ln -s /var/lib/grafana $T/prometheus-$D/grafana
+
+export RSYNC_RSH="ssh -ax"
+
+nice tar --create --dereference --directory=$T prometheus-$D | nice gzip --rsyncable -9 > $T/$B
+nice rsync --preallocate --fuzzy $T/$B backup::backup
+
+rm -rf $T
diff --git a/cookbooks/prometheus/templates/default/chef.prom.erb b/cookbooks/prometheus/templates/default/chef.prom.erb
new file mode 100644 (file)
index 0000000..13b753e
--- /dev/null
@@ -0,0 +1,15 @@
+# HELP chef_network_interface Information about network interfaces
+# TYPE chef_network_interface gauge
+<% node.interfaces do |interface| -%>
+chef_network_interface{name="<%= interface[:interface] %>",role="<%= interface[:role].to_s %>",family="<%= interface[:family].to_s %>"} 1
+<% end -%>
+# HELP chef_role Information about chef roles
+# TYPE chef_role gauge
+<% node[:roles].sort.each do |role| -%>
+chef_role{name="<%= role %>"} 1
+<% end -%>
+<% if node[:roles].include?("tilecache") -%>
+# HELP chef_tile_parent Information about tile cache parents
+# TYPE chef_tile_parent gauge
+chef_tile_parent{name="<%= node[:tilecache][:tile_parent].split(".").first %>"} 1
+<% end -%>
diff --git a/cookbooks/prometheus/templates/default/default.alertmanager.erb b/cookbooks/prometheus/templates/default/default.alertmanager.erb
new file mode 100644 (file)
index 0000000..42d6e3a
--- /dev/null
@@ -0,0 +1,3 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+ARGS="--web.external-url=https://prometheus.openstreetmap.org/alertmanager"
diff --git a/cookbooks/prometheus/templates/default/default.prometheus.erb b/cookbooks/prometheus/templates/default/default.prometheus.erb
new file mode 100644 (file)
index 0000000..451faa7
--- /dev/null
@@ -0,0 +1,3 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+ARGS="--web.external-url=https://prometheus.openstreetmap.org/prometheus"
diff --git a/cookbooks/prometheus/templates/default/grafana.ini.erb b/cookbooks/prometheus/templates/default/grafana.ini.erb
new file mode 100644 (file)
index 0000000..d3ea1ce
--- /dev/null
@@ -0,0 +1,22 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+instance_name = prometheus.openstreetmap.org
+
+[server]
+root_url = https://prometheus.openstreetmap.org/
+
+[security]
+admin_user = admin
+admin_password = <%= @passwords[:grafana_admin] %>
+
+[smtp]
+enabled = true
+host = localhost:25
+skip_verify = true
+from_address = admins@openstreetmap.org
+from_name = Prometheus
+
+[auth.anonymous]
+enabled = true
+org_name = OpenStreetMap
+org_role = Viewer
diff --git a/cookbooks/prometheus/templates/default/prometheus.yml.erb b/cookbooks/prometheus/templates/default/prometheus.yml.erb
new file mode 100644 (file)
index 0000000..d972d29
--- /dev/null
@@ -0,0 +1,115 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+global:
+  scrape_interval: 15s
+  evaluation_interval: 15s
+
+alerting:
+  alertmanagers:
+    - path_prefix: /alertmanager
+      static_configs:
+        - targets:
+            - localhost:9093
+
+rule_files:
+  - /etc/prometheus/*_rules.yml
+
+scrape_configs:
+  - job_name: prometheus
+    scrape_interval: 5s
+    scrape_timeout: 5s
+    metrics_path: /prometheus/metrics
+    static_configs:
+      - targets:
+          - localhost:9090
+  - job_name: alertmanager
+    metrics_path: /alertmanager/metrics
+    static_configs:
+      - targets:
+          - localhost:9093
+  - job_name: promscale
+    static_configs:
+      - targets:
+          - localhost:9201
+  - job_name: ssl
+    scrape_interval: 15m
+    metrics_path: /probe
+    static_configs:
+<% @certificates.values.sort_by { |c| c[:domains].first }.each do |certificate| -%>
+      - targets:
+<% certificate[:nodes].sort_by { |h| h[:name] }.each do |host| -%>
+          - <%= certificate[:domains].first %>/<%= host[:name] %>:443
+<% end -%>
+        labels:
+          domain: <%= certificate[:domains].first %>
+<% end -%>
+    relabel_configs:
+      - source_labels: [__address__]
+        regex: "([^/]+)/.*"
+        target_label: __param_module
+      - source_labels: [__address__]
+        regex: "[^/]+/(.*)"
+        target_label: __param_target
+      - source_labels: [__param_target]
+        regex: "([^.]+)\\..*"
+        target_label: instance
+      - target_label: __address__
+        replacement: 127.0.0.1:9219
+<% @jobs.sort.each do |name, targets| -%>
+  - job_name: <%= name %>
+    static_configs:
+<% targets.each do |target| -%>
+      - targets:
+          - "<%= target[:address] %>"
+        labels:
+          instance: <%= target[:instance] %>
+<% end -%>
+    metric_relabel_configs:
+<% targets.each do |target| -%>
+<% target[:metric_relabel].each do |relabel| -%>
+      - source_labels: [instance,<%= relabel[:source_labels] %>]
+        regex: "<%= target[:instance] %>;<%= relabel[:regex] %>"
+        action: <%= relabel[:action] %>
+<% end -%>
+<% end -%>
+<% end -%>
+  - job_name: snmp
+    scrape_interval: 5m
+    scrape_timeout: 1m
+    metrics_path: /snmp
+    static_configs:
+      - targets:
+<% @snmp_targets.sort_by { |t| t[:instance] }.each do |target| -%>
+      - targets:
+          - "<%= target[:target] %>/<%= target[:module] %>/<%= target[:address] %>"
+        labels:
+          instance: <%= target[:instance] %>
+<% target[:labels].sort.each do |name, value| -%>
+          <%= name %>: <%= value %>
+<% end -%>
+<% end -%>
+    relabel_configs:
+      - source_labels: [__address__]
+        regex: "([^/]+)/[^/]+/.*"
+        target_label: __param_target
+      - source_labels: [__address__]
+        regex: "[^/]+/([^/]+)/.*"
+        target_label: __param_module
+      - source_labels: [__address__]
+        regex: "[^/]+/[^/]+/(.*)"
+        target_label: __address__
+
+remote_write:
+  - url: "http://localhost:9201/write"
+    write_relabel_configs:
+      - source_labels: [__name__]
+        regex: "go_.*"
+        action: drop
+      - source_labels: [__name__]
+        regex: "promhttp_.*"
+        action: drop
+    queue_config:
+      capacity: 10000
+      min_shards: 4
+      batch_send_deadline: 30s
+      max_backoff: 1s
diff --git a/cookbooks/prometheus/templates/default/ssl.yml.erb b/cookbooks/prometheus/templates/default/ssl.yml.erb
new file mode 100644 (file)
index 0000000..be622f4
--- /dev/null
@@ -0,0 +1,7 @@
+modules:
+<% @certificates.values.sort_by { |c| c[:domains].first }.each do |certificate| -%>
+  <%= certificate[:domains].first %>:
+    prober: tcp
+    tls_config:
+      server_name: <%= certificate[:domains].first %>
+<% end -%>
index 53dc4c59ab29de609ab792bffd52891667c59599..00f763bac9a0b7a5c084ac3f98e15900f4e0b908 100644 (file)
 # limitations under the License.
 #
 
-package "python"
-package "python-pip"
+if node[:lsb][:release].to_f < 20.04
+  package "python"
+  package "python-pip"
+end
 
 package "python3"
 package "python3-pip"
 
-package "python-virtualenv"
+package "virtualenv"
index cb372f4c3bb1c1730027d4ae8eed2a1dece99e23..6f07fd895bf69116a18f393e6895be8880bcfa29 100644 (file)
 default_action :create
 
 property :virtualenv_directory, :kind_of => String, :name_property => true
+property :interpreter, :kind_of => String, :default => "/usr/bin/python"
 
 action :create do
   execute "virtualenv-#{new_resource.virtualenv_directory}" do
-    command "virtualenv #{new_resource.virtualenv_directory}"
+    command "virtualenv --python=#{new_resource.interpreter} #{new_resource.virtualenv_directory}"
     not_if { ::File.exist?(new_resource.virtualenv_directory) }
   end
 end
diff --git a/cookbooks/roundup/README.md b/cookbooks/roundup/README.md
deleted file mode 100644 (file)
index a40f953..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# Roundup Cookbook
-
-This is a placeholder cookbook, intended for use with the Roundup Issue Tracker.
index e32c2b7edfd038a7b74b129ed8fb6ca40b27b8a8..38e70fe78a6c2ffdc83735dafe7ca6eb92a2a178 100644 (file)
@@ -7,3 +7,4 @@ description       "Configures rsyncd"
 version           "1.0.0"
 supports          "ubuntu"
 depends           "networking"
+depends           "systemd"
index 7a93fc021fa20cbccb26a3fc67ae13da470da711..a2edd32faf14262009b2448f4136000adc670036 100644 (file)
@@ -42,6 +42,13 @@ end
 
 package "rsync"
 
+systemd_service "rsync-override" do
+  service "rsync"
+  dropin "override"
+  exec_start "/usr/bin/rsync --daemon --no-detach --bwlimit=16384"
+  notifies :restart, "service[rsync]"
+end
+
 service "rsync" do
   action [:enable, :start]
   supports :status => true, :restart => true
@@ -51,7 +58,7 @@ template "/etc/default/rsync" do
   source "rsync.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[rsync]"
 end
 
@@ -59,7 +66,7 @@ template "/etc/rsyncd.conf" do
   source "rsyncd.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   variables :hosts_allow => hosts_allow, :hosts_deny => hosts_deny
 end
 
index f487fa4d18cf87bedad1bcfd5882552ac89c06c0..8d154c66a08ca687d0a875a9e989e79a8fcc0d28 100644 (file)
 include_recipe "apache"
 include_recipe "git"
 
-package "ruby"
-package "ruby-dev"
+package %w[
+  gcc
+  g++
+  make
+  ruby
+  ruby-dev
+  libssl-dev
+  zlib1g-dev
+  pkg-config
+]
 
-gem_package "jekyll"
+gem_package "bundler" do
+  version "1.17.3"
+end
 
 git "/srv/hardware.openstreetmap.org" do
   action :sync
-  repository "git://github.com/gravitystorm/osmf-server-info.git"
+  repository "https://github.com/gravitystorm/osmf-server-info.git"
+  depth 1
   user "root"
   group "root"
-  notifies :run, "execute[/srv/hardware.openstreetmap.org]"
+  notifies :run, "execute[/srv/hardware.openstreetmap.org/Gemfile]"
 end
 
 nodes = { :rows => search(:node, "*:*") }
@@ -38,7 +49,7 @@ roles = { :rows => search(:role, "*:*") }
 
 file "/srv/hardware.openstreetmap.org/_data/nodes.json" do
   content nodes.to_json
-  mode 0o644
+  mode "644"
   owner "root"
   group "root"
   notifies :run, "execute[/srv/hardware.openstreetmap.org]"
@@ -46,21 +57,38 @@ end
 
 file "/srv/hardware.openstreetmap.org/_data/roles.json" do
   content roles.to_json
-  mode 0o644
+  mode "644"
   owner "root"
   group "root"
   notifies :run, "execute[/srv/hardware.openstreetmap.org]"
 end
 
 directory "/srv/hardware.openstreetmap.org/_site" do
-  mode 0o755
+  mode "755"
   owner "nobody"
   group "nogroup"
 end
 
+# Workaround https://github.com/jekyll/jekyll/issues/7804
+# by creating a .jekyll-cache folder
+directory "/srv/hardware.openstreetmap.org/.jekyll-cache" do
+  mode "755"
+  owner "nobody"
+  group "nogroup"
+end
+
+execute "/srv/hardware.openstreetmap.org/Gemfile" do
+  action :nothing
+  command "bundle install --deployment"
+  cwd "/srv/hardware.openstreetmap.org"
+  user "root"
+  group "root"
+  notifies :run, "execute[/srv/hardware.openstreetmap.org]"
+end
+
 execute "/srv/hardware.openstreetmap.org" do
   action :nothing
-  command "jekyll build --trace"
+  command "bundle exec jekyll build --trace --baseurl=https://hardware.openstreetmap.org"
   cwd "/srv/hardware.openstreetmap.org"
   user "nobody"
   group "nogroup"
index 0cba387e1899db761de28619d10a93a1c854b613..3e7c1d1c42db9e38a14180e1aae10a953c2cc2a2 100644 (file)
@@ -1 +1 @@
-default[:rsyncd][:modules] = []
+default[:snmpd][:clients] = []
index ccafc831cc98bd1a6f37aea7f608fd822514f134..98e4c400b7421164aecccf85ac72560f69806868 100644 (file)
@@ -32,7 +32,7 @@ template "/etc/snmp/snmpd.conf" do
   source "snmpd.conf.erb"
   owner "root"
   group "root"
-  mode 0o600
+  mode "600"
   variables :communities => communities
   notifies :restart, "service[snmpd]"
 end
@@ -60,3 +60,27 @@ else
     source_ports "1024:"
   end
 end
+
+if node[:snmpd][:clients6]
+  node[:snmpd][:clients6].each do |address|
+    firewall_rule "accept-snmp" do
+      action :accept
+      family "inet6"
+      source "net:#{address}"
+      dest "fw"
+      proto "udp"
+      dest_ports "snmp"
+      source_ports "1024:"
+    end
+  end
+else
+  firewall_rule "accept-snmp" do
+    action :accept
+    family "inet6"
+    source "net"
+    dest "fw"
+    proto "udp"
+    dest_ports "snmp"
+    source_ports "1024:"
+  end
+end
index 9239fbd309aaa7a90836264e51edd436578b0521..3b79ad1f8a65e4b73fd9530248483573e1fe399c 100644 (file)
@@ -1,6 +1,9 @@
 # DO NOT EDIT - This file is being maintained by Chef
 
-rocommunity     <%= @communities[node[:snmpd][:community]] %>
+<% Array(@communities[node[:snmpd][:community]]).each do |community| -%>  
+rocommunity     <%= community %>
+rocommunity6    <%= community %>
+<% end -%>
 syslocation     <%= node[:snmpd][:location] %>
 <% if node[:snmpd][:contact] -%>
 syscontact      <%= node[:snmpd][:contact] %>
index 470463eafce467cb3d9a9dac59f8df88f0478a9d..acd564bf7a62c52d8cd0045f6de3ba96a7773007 100644 (file)
@@ -6,3 +6,4 @@ description       "Installs and configures spamassassin"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "exim"
index 49b15a583da44975fd1232d3381b5bdd9b81eece..d9af52bd1bbdc816cb415c7131286cbde2ef0f6a 100644 (file)
@@ -27,14 +27,14 @@ end
 directory "/var/spool/spamassassin" do
   owner "debian-spamd"
   group "debian-spamd"
-  mode 0o755
+  mode "755"
 end
 
 template "/etc/default/spamassassin" do
   source "spamassassin.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :restart, "service[spamassassin]"
 end
 
@@ -52,7 +52,7 @@ template "/etc/spamassassin/local.cf" do
   source "local.cf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   variables :trusted_networks => trusted_networks.sort
   notifies :restart, "service[spamassassin]"
 end
index 286d1feeb9bd5a0e091083d9baf36d371438f459..1f5769d502c42462a8f4a42ec476160c85255506 100644 (file)
@@ -10,7 +10,7 @@ ENABLED=1
 # make sure --max-children is not set to anything higher than 5,
 # unless you know what you're doing.
 
-OPTIONS="--username debian-spamd --nouser-config"
+OPTIONS="--username debian-spamd --nouser-config --max-children=20 --max-spare=5"
 
 # Pid file
 # Where should spamd write its PID to file? If you use the -u or
index e3e2ca83eafffa8da2a43e0ef7d753d0341621fb..ea3b97375dd51dee625487017b5f2501bad9702d 100644 (file)
@@ -1,6 +1,7 @@
-default[:squid][:version] = 2
+default[:squid][:version] = 4
 default[:squid][:cache_mem] = "256 MB"
 default[:squid][:cache_dir] = "ufs /var/spool/squid 256 16 256"
 default[:squid][:access_log] = "/var/log/squid/access.log openstreetmap"
+default[:squid][:private_devices] = true
 
 default[:apt][:sources] = node[:apt][:sources] | ["squid#{node[:squid][:version]}"]
index 6f9dcc7239acad363cdf43598a515873cef500a2..07b04b8f381765d0b9ccae9914dbbb080a9d96d1 100644 (file)
@@ -6,4 +6,7 @@ description       "Installs and configures squid"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "apt"
+depends           "munin"
+depends           "prometheus"
 depends           "systemd"
index c2bd5b834c6b5e49b56f188de7c8f09df3b6adc5..deeff85b6373c5d1ba3657930fd32ba6b6b01c3e 100644 (file)
 # limitations under the License.
 #
 
+include_recipe "apt"
+include_recipe "munin"
+include_recipe "prometheus"
+
 if node[:squid][:version] >= 3
   apt_package "squid" do
     action :unlock
@@ -53,13 +57,13 @@ template "/etc/squid/squid.conf" do
   source "squid.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 directory "/etc/squid/squid.conf.d" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 Array(node[:squid][:cache_dir]).each do |cache_dir|
@@ -72,7 +76,7 @@ Array(node[:squid][:cache_dir]).each do |cache_dir|
   directory cache_dir do
     owner "proxy"
     group "proxy"
-    mode 0o750
+    mode "750"
     recursive true
     notifies :restart, "service[squid]"
   end
@@ -85,40 +89,51 @@ systemd_tmpfile "/var/run/squid" do
   mode "0755"
 end
 
-address_families = %w[AF_UNIX AF_INET]
+address_families = %w[AF_UNIX AF_INET AF_INET6]
+
+file "/etc/systemd/system/squid.service" do
+  action :delete
+end
 
-# address_families << "AF_INET6" unless node.interfaces(:family => :inet6).empty?
+file "/etc/logrotate.d/squid.dpkg-dist" do
+  action :delete
+end
+
+squid_service_exec = if node[:lsb][:release].to_f < 20.04
+                       "/usr/sbin/squid -YC"
+                     else
+                       "/usr/sbin/squid --foreground -YC"
+                     end
 
 systemd_service "squid" do
-  description "Squid caching proxy"
-  after ["network.target", "nss-lookup.target"]
-  type "forking"
+  dropin "chef"
   limit_nofile 98304
-  exec_start_pre "/usr/sbin/squid -N -z"
-  exec_start "/usr/sbin/squid -Y"
-  exec_reload "/usr/sbin/squid -k reconfigure"
-  exec_stop "/usr/sbin/squid -k shutdown"
   private_tmp true
-  private_devices true
+  private_devices node[:squid][:private_devices]
   protect_system "full"
   protect_home true
   restrict_address_families address_families
-  restart "on-failure"
-  timeout_sec 0
+  restart "always"
+  exec_start "#{squid_service_exec}"
 end
 
 service "squid" do
-  action [:enable, :start]
+  action :enable
   subscribes :restart, "systemd_service[squid]"
-  subscribes :reload, "template[/etc/squid/squid.conf]"
+  subscribes :restart, "template[/etc/squid/squid.conf]"
   subscribes :reload, "template[/etc/resolv.conf]"
 end
 
-log "squid-restart" do
-  message "Restarting squid due to counter wraparound"
-  notifies :restart, "service[squid]"
+notify_group "squid-start" do
+  action :run
+  notifies :start, "service[squid]"
+end
+
+service "squid-restart" do
+  service_name "squid"
+  action :restart
   only_if do
-    IO.popen(["squidclient", "--host=127.0.0.1", "--port=80", "mgr:counters"]) do |io|
+    IO.popen(["squidclient", "--host=127.0.0.1", "--port=3128", "mgr:counters"]) do |io|
       io.each.grep(/^[a-z][a-z_.]+ = -[0-9]+$/).count.positive?
     end
   end
@@ -138,3 +153,8 @@ end
 munin_plugin "squid_delay_pools_noreferer" do
   action :delete
 end
+
+prometheus_exporter "squid" do
+  port 9301
+  listen_switch "listen"
+end
index d3778c4ac2959a256631e58e571ac6fd803e4d53..f4099ad7bd9fb4b62b0a753bee8f56d50342382d 100644 (file)
@@ -19,8 +19,8 @@
 
 default_action :create
 
-property :fragment, :kind_of => String, :name_attribute => true
-property :template, :kind_of => String, :required => true
+property :fragment, :kind_of => String, :name_property => true
+property :template, :kind_of => String, :required => [:create]
 property :variables, :kind_of => Hash, :default => {}
 
 action :create do
@@ -28,7 +28,7 @@ action :create do
     source new_resource.template
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables new_resource.variables
   end
 end
index 51dc0b63ee885cb6afd481a9cd4bfad706a9d27b..61008078a70535764f4182fc363e90afdf3f0bf9 100644 (file)
@@ -1,39 +1,53 @@
 # DO NOT EDIT - This file is being maintained by Chef
 
-#configure host name
+# configure host name
 visible_hostname <%= node.name %>
 
-#FIXME - configurable
 cache_mem  <%= node[:squid][:cache_mem] %>
 <% if node[:squid][:version] > 2 -%>
 
-workers <%= node[:cpu][:total] %>
+workers <%= [ node[:cpu][:total] - 2, 1 ].max.ceil %>
+cpu_affinity_map process_numbers=<%= (1..[ node[:cpu][:total] - 2, 1 ].max.ceil).to_a.join(',') %> cores=<%=(1..[ node[:cpu][:total] - 2, 1 ].max.ceil).to_a.join(',') %>
+
+# Set short clean shutdown interval
+shutdown_lifetime 2 seconds
 
 error_log_languages off
 <% end -%>
 
 max_filedescriptors 98304
 
-#used by squidclient / munin
+<% if node[:squid][:version] > 3 -%>
+# Use RFC6891 recommended max size
+dns_packet_max 4096 bytes
+# Use low initial retry interval (backoff start)
+dns_retransmit_interval 2 seconds
+# Set low timeout
+dns_timeout 15 seconds
+<% end -%>
+dns_v4_first on
+
+# used by squidclient / munin
 http_port 3128
-#ICP
+# HTCP
+htcp_port 4827
+# ICP
 icp_port 3130
 log_icp_queries off
 
-#FIXME - configurable
 <% if node[:squid][:version] < 3 -%>
 http_port 80 accel defaultsite=tile.openstreetmap.org tcpkeepalive=60,10,6 http11
 <% else -%>
-http_port 80 accel no-vhost defaultsite=tile.openstreetmap.org tcpkeepalive=60,10,6
+http_port 8080 accel no-vhost defaultsite=tile.openstreetmap.org tcpkeepalive=60,10,6
 <% end -%>
 
 cache_effective_user proxy
 cache_effective_group proxy
 
-#FIXME - configurable
 <% Array(node[:squid][:cache_dir]).each do |cache_dir| -%>
 cache_dir <%= cache_dir %>
 <% end -%>
+
 <% if node[:squid][:version] < 3 -%>
 cache_swap_log /var/spool/squid/%s
 <% end -%>
@@ -45,7 +59,7 @@ quick_abort_max 0 KB
 
 read_ahead_gap 64 KB
 
-maximum_object_size 1048576 bytes
+maximum_object_size 256 KB
 maximum_object_size_in_memory 64 KB
 
 cache_replacement_policy heap LFUDA
@@ -62,11 +76,8 @@ pconn_lifetime 5 minutes
 <% end -%>
 
 negative_ttl 15 seconds
-half_closed_clients off
 <% if node[:squid][:version] < 3 -%>
 pipeline_prefetch on
-<% else -%>
-pipeline_prefetch 1
 <% end -%>
 
 read_timeout 90 seconds
@@ -74,15 +85,12 @@ request_timeout 90 seconds
 connect_timeout 20 seconds
 client_lifetime 1 hours
 
-<% if node[:squid][:version] < 4 -%>
-collapsed_forwarding on
-<% end -%>
 <% if node[:squid][:version] < 3 -%>
 refresh_stale_hit 300 seconds
 <% end -%>
 
-#Recommended minimum configuration:
-#----------------------------------
+# Recommended minimum configuration:
+# ----------------------------------
 <% if node[:squid][:version] < 3 -%>
 acl all src all
 acl manager proto cache_object
@@ -108,7 +116,7 @@ http_access allow manager
 http_access deny manager
 http_access deny !Safe_ports
 http_access deny CONNECT !SSL_ports
-#----------------------------------
+# ----------------------------------
 
 acl purge_hosts src 127.0.0.0/8
 acl PURGE method purge
@@ -127,7 +135,9 @@ access_log daemon:<%= node[:squid][:access_log] %>
 <% end -%>
 cache_log /var/log/squid/cache.log
 cache_store_log none
+
 buffered_logs on
+
 client_db off
 strip_query_terms off
 <% if node[:squid][:version] > 2 -%>
@@ -138,20 +148,21 @@ url_rewrite_extras "%>a %un %>rm myip=%la myport=%lp"
 store_id_extras "%>a %un %>rm myip=%la myport=%lp"
 <% end -%>
 
-digest_generation on
+digest_generation off
 
-refresh_pattern .              0       50%     8640
+refresh_pattern .              0       50%     20160
+refresh_pattern -i tile.openstreetmap.org 60 80% 20160 reload-into-ims
 
-#ZERO required for logrotate to work properly
+# ZERO required for logrotate to work properly
 logfile_rotate 0
 
 <% Dir.glob("/etc/squid/squid.conf.d/*.conf") do |file| -%>
 <%= File.read(file) %>
 <% end -%>
 
-#MUST BE LAST ACL
-#--------------
+# MUST BE LAST ACL
+# --------------
 http_access deny all
+htcp_access deny all
 icp_access deny all
-#--------------
-
+# --------------
index 55c7ebee5479cb9a2465c63ab235c05a895ac0b7..0725996d62948986121f64db5f9c2f0c003fbace 100644 (file)
@@ -1,3 +1,4 @@
 default[:ssl][:openssl_ciphers] = "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS"
 default[:ssl][:gnutls_ciphers] = "NONE:+AEAD:+SHA256:+SHA1:+SHA384:+SHA512:+CURVE-X25519:+CURVE-SECP256R1:+CURVE-SECP384R1:+CURVE-SECP521R1:+SIGN-ALL:-SIGN-RSA-MD5:-SIGN-DSA-SHA1:-SIGN-DSA-SHA224:-SIGN-DSA-SHA256:-SIGN-DSA-SHA384:-SIGN-DSA-SHA512:+AES-256-GCM:+AES-256-CCM:+CHACHA20-POLY1305:+CAMELLIA-256-GCM:+AES-256-CBC:+CAMELLIA-256-CBC:+AES-128-GCM:+AES-128-CCM:+CAMELLIA-128-GCM:+AES-128-CBC:+CAMELLIA-128-CBC:+ECDHE-RSA:+ECDHE-ECDSA:+RSA:+DHE-RSA:+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-DTLS1.2:+VERS-DTLS1.0:+COMP-NULL:%PROFILE_LOW"
 default[:ssl][:strict_transport_security] = "max-age=31536000; includeSubDomains; preload"
+default[:ssl][:ct_report_uri] = "https://openstreetmap.report-uri.com/r/d/ct/reportOnly"
diff --git a/cookbooks/ssl/files/default/dhparam.pem b/cookbooks/ssl/files/default/dhparam.pem
new file mode 100644 (file)
index 0000000..9b182b7
--- /dev/null
@@ -0,0 +1,8 @@
+-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
+87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
+YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
+7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
+ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
+-----END DH PARAMETERS-----
diff --git a/cookbooks/ssl/files/default/letsencrypt.pem b/cookbooks/ssl/files/default/letsencrypt.pem
deleted file mode 100644 (file)
index 0002462..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
-MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
-DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
-SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
-GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
-q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
-SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
-Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
-a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
-/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
-AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
-CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
-bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
-c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
-VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
-ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
-MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
-Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
-AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
-uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
-wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
-X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
-PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
-KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
------END CERTIFICATE-----
index 674c8768d24f897f95199939a5e6e4ac65209d3b..17bb6339ecf4bf2e4aa5324a6c5c518ee85598da 100644 (file)
 package "openssl"
 package "ssl-cert"
 
-cookbook_file "/etc/ssl/certs/letsencrypt.pem" do
+cookbook_file "/etc/ssl/certs/dhparam.pem" do
   owner "root"
   group "root"
-  mode 0o444
+  mode "444"
   backup false
 end
-
-openssl_dhparam "/etc/ssl/certs/dhparam.pem" do
-  owner "root"
-  group "root"
-  mode 0o444
-end
index fdbcf2b526404f4ee82d79196979abbdf6b3ad8c..5fc33b61be6e8a992b048967fbc86f6c85755ae2 100644 (file)
 default_action :create
 
 property :certificate, String, :name_property => true
-property :domains, [String, Array], :required => true
+property :domains, [String, Array], :required => [:create]
 
 action :create do
   node.default[:letsencrypt][:certificates][new_resource.certificate] = {
-    :domains => Array(new_resource.domains)
+    :domains => domains
   }
 
   if letsencrypt
@@ -36,7 +36,7 @@ action :create do
     file "/etc/ssl/certs/#{new_resource.certificate}.pem" do
       owner "root"
       group "root"
-      mode 0o444
+      mode "444"
       content certificate
       backup false
       manage_symlink_source false
@@ -46,23 +46,23 @@ action :create do
     file "/etc/ssl/private/#{new_resource.certificate}.key" do
       owner "root"
       group "ssl-cert"
-      mode 0o440
+      mode "440"
       content key
       backup false
       manage_symlink_source false
       force_unlink true
     end
   else
-    alt_names = new_resource.domains.collect { |domain| "DNS:#{domain}" }
+    alt_names = domains.collect { |domain| "DNS:#{domain}" }
 
     openssl_x509_certificate "/etc/ssl/certs/#{new_resource.certificate}.pem" do
       key_file "/etc/ssl/private/#{new_resource.certificate}.key"
       owner "root"
       group "ssl-cert"
-      mode 0o640
+      mode "640"
       org "OpenStreetMap"
       email "operations@osmfoundation.org"
-      common_name new_resource.domains.first
+      common_name domains.first
       subject_alt_name alt_names
       extensions "keyUsage" => { "values" => %w[digitalSignature keyEncipherment], "critical" => true },
                  "extendedKeyUsage" => { "values" => %w[serverAuth clientAuth], "critical" => true }
@@ -84,4 +84,8 @@ action_class do
   def letsencrypt
     @letsencrypt ||= search(:letsencrypt, "id:#{new_resource.certificate}").first
   end
+
+  def domains
+    Array(new_resource.domains)
+  end
 end
index c9eb827d5c56c5962a3063158eabdecb61b61993..0d55936e00f133d3a863c55e6b95d6b362ebfdca 100644 (file)
@@ -25,6 +25,7 @@ git "/srv/stateofthemap.org" do
   action :sync
   repository "https://git.openstreetmap.org/public/stateofthemap.git"
   revision "chooser"
+  depth 1
   user "root"
   group "root"
 end
@@ -44,7 +45,7 @@ end
 directory "/srv/2007.stateofthemap.org" do
   owner "wordpress"
   group "wordpress"
-  mode 0o755
+  mode "755"
 end
 
 wordpress_site "2007.stateofthemap.org" do
@@ -54,6 +55,7 @@ wordpress_site "2007.stateofthemap.org" do
   database_user "sotm2007"
   database_password passwords["sotm2007"]
   database_prefix "wp_sotm_"
+  fpm_prometheus_port 12007
 end
 
 wordpress_theme "2007.stateofthemap.org-refreshwp-11" do
@@ -71,7 +73,7 @@ end
 directory "/srv/2008.stateofthemap.org" do
   owner "wordpress"
   group "wordpress"
-  mode 0o755
+  mode "755"
 end
 
 wordpress_site "2008.stateofthemap.org" do
@@ -81,6 +83,7 @@ wordpress_site "2008.stateofthemap.org" do
   database_user "sotm2008"
   database_password passwords["sotm2008"]
   database_prefix "wp_sotm08_"
+  fpm_prometheus_port 12008
 end
 
 wordpress_theme "2008.stateofthemap.org-refreshwp-11" do
@@ -98,13 +101,14 @@ end
 directory "/srv/2009.stateofthemap.org" do
   owner "wordpress"
   group "wordpress"
-  mode 0o755
+  mode "755"
 end
 
 git "/srv/2009.stateofthemap.org" do
   action :sync
   repository "https://git.openstreetmap.org/public/stateofthemap.git"
   revision "resources-2009"
+  depth 1
   user "wordpress"
   group "wordpress"
 end
@@ -118,6 +122,7 @@ wordpress_site "2009.stateofthemap.org" do
   urls "/register" => "/srv/2009.stateofthemap.org/register",
        "/register-pro-user" => "/srv/2009.stateofthemap.org/register-pro-user",
        "/podcasts" => "/srv/2009.stateofthemap.org/podcasts"
+  fpm_prometheus_port 12009
 end
 
 wordpress_theme "2009.stateofthemap.org-aerodrome" do
@@ -135,13 +140,14 @@ end
 directory "/srv/2010.stateofthemap.org" do
   owner "wordpress"
   group "wordpress"
-  mode 0o755
+  mode "755"
 end
 
 git "/srv/2010.stateofthemap.org" do
   action :sync
   repository "https://git.openstreetmap.org/public/stateofthemap.git"
   revision "resources-2010"
+  depth 1
   user "wordpress"
   group "wordpress"
 end
@@ -153,6 +159,7 @@ wordpress_site "2010.stateofthemap.org" do
   database_user "sotm2010"
   database_password passwords["sotm2010"]
   urls "/register" => "/srv/2010.stateofthemap.org/register"
+  fpm_prometheus_port 12010
 end
 
 wordpress_theme "2010.stateofthemap.org-aerodrome" do
@@ -166,6 +173,7 @@ wordpress_plugin "2010.stateofthemap.org-sitepress-multilingual-cms" do
   plugin "sitepress-multilingual-cms"
   site "2010.stateofthemap.org"
   repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
+  not_if { ENV["TEST_KITCHEN"] }
 end
 
 wordpress_plugin "2010.stateofthemap.org-wp-sticky" do
@@ -176,13 +184,14 @@ end
 directory "/srv/2011.stateofthemap.org" do
   owner "wordpress"
   group "wordpress"
-  mode 0o755
+  mode "755"
 end
 
 git "/srv/2011.stateofthemap.org" do
   action :sync
   repository "https://git.openstreetmap.org/public/stateofthemap.git"
   revision "resources-2011"
+  depth 1
   user "wordpress"
   group "wordpress"
 end
@@ -194,6 +203,7 @@ wordpress_site "2011.stateofthemap.org" do
   database_user "sotm2011"
   database_password passwords["sotm2011"]
   urls "/register" => "/srv/2011.stateofthemap.org/register"
+  fpm_prometheus_port 12011
 end
 
 wordpress_theme "2011.stateofthemap.org-aerodrome" do
@@ -207,6 +217,7 @@ wordpress_plugin "2011.stateofthemap.org-sitepress-multilingual-cms" do
   plugin "sitepress-multilingual-cms"
   site "2011.stateofthemap.org"
   repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
+  not_if { ENV["TEST_KITCHEN"] }
 end
 
 wordpress_plugin "2011.stateofthemap.org-wp-sticky" do
@@ -217,13 +228,14 @@ end
 directory "/srv/2012.stateofthemap.org" do
   owner "wordpress"
   group "wordpress"
-  mode 0o755
+  mode "755"
 end
 
 git "/srv/2012.stateofthemap.org" do
   action :sync
   repository "https://git.openstreetmap.org/public/stateofthemap.git"
   revision "resources-2012"
+  depth 1
   user "wordpress"
   group "wordpress"
 end
@@ -235,6 +247,7 @@ wordpress_site "2012.stateofthemap.org" do
   database_user "sotm2012"
   database_password passwords["sotm2012"]
   urls "/register" => "/srv/2012.stateofthemap.org/register"
+  fpm_prometheus_port 12012
 end
 
 wordpress_theme "2012.stateofthemap.org-aerodrome" do
@@ -253,6 +266,7 @@ wordpress_plugin "2012.stateofthemap.org-sitepress-multilingual-cms" do
   plugin "sitepress-multilingual-cms"
   site "2012.stateofthemap.org"
   repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
+  not_if { ENV["TEST_KITCHEN"] }
 end
 
 wordpress_plugin "2012.stateofthemap.org-wp-sticky" do
@@ -265,12 +279,13 @@ end
     action :sync
     repository "https://git.openstreetmap.org/public/stateofthemap.git"
     revision "site-#{year}"
+    depth 1
     user "root"
     group "root"
   end
 
   ssl_certificate "#{year}.stateofthemap.org" do
-    domains ["#{year}.stateofthemap.org", "#{year}.stateofthemap.com"]
+    domains ["#{year}.stateofthemap.org", "#{year}.stateofthemap.com", "#{year}.sotm.org"]
     notifies :reload, "service[apache2]"
   end
 
@@ -282,26 +297,39 @@ end
 end
 
 package %w[
+  gcc
+  g++
+  make
   ruby
   ruby-dev
+  libssl-dev
   zlib1g-dev
+  pkg-config
 ]
 
+apache_module "expires"
+apache_module "rewrite"
+
 gem_package "bundler" do
   version "1.17.3"
 end
 
-%w[2016 2017 2018 2019 2020].each do |year|
+gem_package "bundler" do
+  version "2.1.4"
+end
+
+%w[2016 2017 2018 2019 2020 2021].each do |year|
   git "/srv/#{year}.stateofthemap.org" do
     action :sync
-    repository "git://github.com/openstreetmap/stateofthemap-#{year}.git"
+    repository "https://github.com/openstreetmap/stateofthemap-#{year}.git"
+    depth 1
     user "root"
     group "root"
     notifies :run, "execute[/srv/#{year}.stateofthemap.org/Gemfile]"
   end
 
   directory "/srv/#{year}.stateofthemap.org/_site" do
-    mode 0o755
+    mode "755"
     owner "nobody"
     group "nogroup"
   end
@@ -309,7 +337,7 @@ end
   # Workaround https://github.com/jekyll/jekyll/issues/7804
   # by creating a .jekyll-cache folder
   directory "/srv/#{year}.stateofthemap.org/.jekyll-cache" do
-    mode 0o755
+    mode "755"
     owner "nobody"
     group "nogroup"
   end
@@ -321,7 +349,6 @@ end
     user "root"
     group "root"
     notifies :run, "execute[/srv/#{year}.stateofthemap.org]"
-    # Workaround until 2019 until merged https://github.com/openstreetmap/stateofthemap-2019/pull/46
     only_if { ::File.exist?("/srv/#{year}.stateofthemap.org/Gemfile") }
   end
 
@@ -334,7 +361,7 @@ end
   end
 
   ssl_certificate "#{year}.stateofthemap.org" do
-    domains ["#{year}.stateofthemap.org", "#{year}.stateofthemap.com"]
+    domains ["#{year}.stateofthemap.org", "#{year}.stateofthemap.com", "#{year}.sotm.org"]
     notifies :reload, "service[apache2]"
   end
 
@@ -349,6 +376,6 @@ template "/etc/cron.daily/sotm-backup" do
   source "backup.cron.erb"
   owner "root"
   group "root"
-  mode 0o750
+  mode "750"
   variables :passwords => passwords
 end
index 7cea946c43929f2615c061ec1afd45b1a1f10326..7cca3c5a1341bcd5b3344a55ecb99c5e26b762a0 100644 (file)
         SSLCertificateKeyFile /etc/ssl/private/stateofthemap.org.key
 
         DocumentRoot /srv/stateofthemap.org/html
+
+        ErrorDocument 404 /404.html
+
+        ExpiresActive On
+        ExpiresDefault "access plus 12 hours"
 </VirtualHost>
 
 <Directory /srv/stateofthemap.org/html>
index 4010ce4bbea10f9653380f36ad51c7f82dae374c..504003df60a9bbe221d8f8c97bc197db7bf4f720 100644 (file)
@@ -2,7 +2,7 @@
 
 <VirtualHost *:80>
         ServerName <%= @year %>.stateofthemap.org
-        ServerAlias <%= @year %>.stateofthemap.com
+        ServerAlias <%= @year %>.stateofthemap.com <%= @year %>.sotm.org
         ServerAdmin webmaster@openstreetmap.org
 
         CustomLog /var/log/apache2/<%= @year %>.stateofthemap.org-access.log combined
@@ -14,6 +14,7 @@
 
 <VirtualHost *:443>
         ServerName <%= @year %>.stateofthemap.com
+        ServerAlias <%= @year %>.sotm.org
         ServerAdmin webmaster@openstreetmap.org
 
         CustomLog /var/log/apache2/<%= @year %>.stateofthemap.org-access.log combined
         SSLCertificateKeyFile /etc/ssl/private/<%= @year %>.stateofthemap.org.key
 
         DocumentRoot /srv/<%= @year %>.stateofthemap.org/_site
+
+        ErrorDocument 404 /404.html
+
+        ExpiresActive On
+        ExpiresDefault "access plus 10 minutes"
 </VirtualHost>
 
 <Directory /srv/<%= @year %>.stateofthemap.org/_site>
index af83be7a9963a4865d09b99c9bf75aa4df9b7243..07ec18cbe2dc4a343e11e09c241ec07cdeb020d8 100644 (file)
@@ -2,7 +2,7 @@
 
 <VirtualHost *:80>
         ServerName <%= @year %>.stateofthemap.org
-        ServerAlias <%= @year %>.stateofthemap.com
+        ServerAlias <%= @year %>.stateofthemap.com <%= @year %>.sotm.org
         ServerAdmin webmaster@openstreetmap.org
 
         CustomLog /var/log/apache2/<%= @year %>.stateofthemap.org-access.log combined
@@ -14,6 +14,7 @@
 
 <VirtualHost *:443>
         ServerName <%= @year %>.stateofthemap.com
+        ServerAlias <%= @year %>.sotm.org
         ServerAdmin webmaster@openstreetmap.org
 
         CustomLog /var/log/apache2/<%= @year %>.stateofthemap.org-access.log combined
         SSLCertificateKeyFile /etc/ssl/private/<%= @year %>.stateofthemap.org.key
 
         DocumentRoot /srv/<%= @year %>.stateofthemap.org
+
+        ErrorDocument 404 /404.html
+
+        ExpiresActive On
+        ExpiresDefault "access plus 7 days"
 </VirtualHost>
 
 <Directory /srv/<%= @year %>.stateofthemap.org>
index cb7171b6f5dd82464c922b70849c0f69b93c15bd..20ff1588854af2be8ef08dcca12af29145d2a99f 100644 (file)
@@ -12,7 +12,7 @@ mkdir $T/sotm-$D
 echo '[mysqldump]' > $T/mysqldump.opts
 echo 'user=sotm<%= year %>' >> $T/mysqldump.opts
 echo 'password=<%= @passwords["sotm#{year}"] %>' >> $T/mysqldump.opts
-mysqldump --defaults-file=$T/mysqldump.opts --opt sotm<%= year %> > $T/sotm-$D/sotm<%= year %>.sql
+mysqldump --defaults-file=$T/mysqldump.opts --opt --no-tablespaces sotm<%= year %> > $T/sotm-$D/sotm<%= year %>.sql
 <% end -%>
 
 ln -s /srv/2007.stateofthemap.org $T/sotm-$D/www2007
@@ -23,10 +23,9 @@ ln -s /srv/2011.stateofthemap.org $T/sotm-$D/www2011
 ln -s /srv/2012.stateofthemap.org $T/sotm-$D/www2012
 ln -s /srv/2016.stateofthemap.org $T/sotm-$D/www2016
 
-export GZIP="--rsyncable -9"
 export RSYNC_RSH="ssh -ax"
 
-nice tar --create --gzip --dereference --directory=$T --file=$T/$B sotm-$D
+nice tar --create --dereference --directory=$T sotm-$D | nice gzip --rsyncable -9 > $T/$B
 nice rsync --preallocate --fuzzy $T/$B backup::backup
 
 rm -rf $T
index 7014c2d5fa5f74e9735121b0e43f2f3c40e1c262..f38efb7b80fafd6a0623797a4b15ea2021baf72c 100644 (file)
@@ -27,10 +27,10 @@ remote_directory "#{repository_directory}/hooks" do
   source "hooks"
   owner "www-data"
   group "www-data"
-  mode 0o755
+  mode "755"
   files_owner "www-data"
   files_group "www-data"
-  files_mode 0o755
+  files_mode "755"
   purge false
 end
 
@@ -43,11 +43,11 @@ apache_module "dav_fs" do
 end
 
 apache_module "dav_svn" do
-  package "libapache2-svn"
+  package "libapache2-mod-svn"
 end
 
 apache_module "authz_svn" do
-  package "libapache2-svn"
+  package "libapache2-mod-svn"
 end
 
 ssl_certificate "svn.openstreetmap.org" do
@@ -65,5 +65,5 @@ template "/etc/cron.daily/svn-backup" do
   source "backup.cron.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
index 42e4592e6a7edb8bb4db328f537c9eb44d36a81e..cadae8b0892055d4cef99aeaeb41ef24e0f62623 100644 (file)
     SVNPath <%= @directory %>
     SVNIndexXSLT /svnindex.xsl
 
-    AuthType Basic
-    AuthName "<%= @realm %>"
-    AuthUserFile <%= @password_file %>
-
     LimitXMLRequestBody 0
     LimitRequestBody 0
 
@@ -31,7 +27,7 @@
     </Limit>
 
     <LimitExcept GET PROPFIND OPTIONS REPORT>
-      Require valid-user
+      Require all denied
     </LimitExcept>
   </Location>
 </VirtualHost>
index df7b4fe28f880d38b60508b698b080daa78efa59..d82348da86b7c7ef6fbe4023b2f2e65c26ba0635 100644 (file)
@@ -8,10 +8,9 @@ B=svn-$D.tar.gz
 
 nice svnadmin hotcopy /var/lib/subversion/repos/openstreetmap $T/svn-$D > /dev/null
 
-export GZIP="--rsyncable -9"
 export RSYNC_RSH="ssh -ax"
 
-nice tar --create --gzip --directory=$T --file=$T/$B svn-$D
+nice tar --create --directory=$T svn-$D | nice gzip --rsyncable -9 > $T/$B
 nice rsync --preallocate --fuzzy $T/$B backup::backup
 
 rm -rf $T
diff --git a/cookbooks/supybot/attributes/default.rb b/cookbooks/supybot/attributes/default.rb
new file mode 100644 (file)
index 0000000..1e8be78
--- /dev/null
@@ -0,0 +1 @@
+default[:accounts][:users][:supybot][:status] = :role
index 1b372ae221fa91f82bcbb36961a609657ebdcdf7..76dbe20f28c1a589eef21a178f18ec87b8617f57 100644 (file)
@@ -6,4 +6,5 @@ description       "Installs and configures supybot"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "systemd"
index d1c1ea32d8f9e17b1ece07f0fcfb5f9a374120de..68d8eb7447e53891bbc87a513d70e5b3d067baeb 100644 (file)
 # limitations under the License.
 #
 
+include_recipe "accounts"
+
 users = data_bag_item("supybot", "users")
 passwords = data_bag_item("supybot", "passwords")
 
-package "supybot"
-package "python-git"
+package "limnoria"
+package "python3-git"
 
 directory "/etc/supybot" do
   owner "supybot"
   group "supybot"
-  mode 0o755
+  mode "755"
 end
 
 template "/etc/supybot/supybot.conf" do
   source "supybot.conf.erb"
   owner "supybot"
   group "supybot"
-  mode 0o644
+  mode "644"
   variables :passwords => passwords
 end
 
@@ -41,84 +43,85 @@ template "/etc/supybot/channels.conf" do
   source "channels.conf.erb"
   owner "supybot"
   group "supybot"
-  mode 0o644
+  mode "644"
 end
 
 template "/etc/supybot/git.conf" do
   source "git.conf.erb"
   owner "supybot"
   group "supybot"
-  mode 0o644
+  mode "644"
 end
 
 template "/etc/supybot/ignores.conf" do
   source "ignores.conf.erb"
   owner "supybot"
   group "supybot"
-  mode 0o644
+  mode "644"
 end
 
 template "/etc/supybot/userdata.conf" do
   source "userdata.conf.erb"
   owner "supybot"
   group "supybot"
-  mode 0o644
+  mode "644"
 end
 
 template "/etc/supybot/users.conf" do
   source "users.conf.erb"
   owner "supybot"
   group "supybot"
-  mode 0o644
+  mode "644"
   variables :passwords => users
 end
 
 directory "/var/lib/supybot" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 directory "/var/lib/supybot/data" do
   owner "supybot"
   group "supybot"
-  mode 0o755
+  mode "755"
 end
 
 directory "/var/lib/supybot/backup" do
   owner "supybot"
   group "supybot"
-  mode 0o755
+  mode "755"
 end
 
 directory "/var/lib/supybot/git" do
   owner "supybot"
   group "supybot"
-  mode 0o755
+  mode "755"
 end
 
 directory "/var/log/supybot" do
   owner "supybot"
   group "supybot"
-  mode 0o755
+  mode "755"
 end
 
 directory "/usr/local/lib/supybot" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 directory "/usr/local/lib/supybot/plugins" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 git "/usr/local/lib/supybot/plugins/Git" do
   action :sync
-  repository "git://github.com/openstreetmap/supybot-git"
+  repository "https://github.com/openstreetmap/supybot-git"
   revision "master"
+  depth 1
   user "root"
   group "root"
 end
index 0afacce9261cfe2bd522cfabb07d5f2c2bc7852d..fa744416682273ff62f0a0fea0c65589113d2867 100644 (file)
@@ -1,5 +1,4 @@
 # DO NOT EDIT - This file is being maintained by Chef
-# Note use git:// protocol instead of ssh based to avoid host key verification issue
 
 [osm-website]
 short name = osm-website
@@ -73,23 +72,15 @@ commit message = [%s|%b|%a] %m %l
 
 [osm-carto]
 short name = osm-carto
-url = git://github.com/gravitystorm/openstreetmap-carto.git
+url = https://github.com/gravitystorm/openstreetmap-carto.git
 branch = master
 commit link = https://github.com/gravitystorm/openstreetmap-carto/commit/%c
 channels = #osm-dev
 commit message = [%s|%b|%a] %m %l
 
-[osm-carto-schema]
-short name = osm-carto-schema
-url = git://github.com/gravitystorm/openstreetmap-carto.git
-branch = schema_changes
-commit link = https://github.com/gravitystorm/openstreetmap-carto/commit/%c
-channels = #osm-dev
-commit message = [%s|%b|%a] %m %l
-
 [osm-osm2pgsql]
 short name = osm-osm2pgsql
-url = git://github.com/openstreetmap/osm2pgsql.git
+url = https://github.com/openstreetmap/osm2pgsql.git
 branch = master
 commit link = https://github.com/openstreetmap/osm2pgsql/commit/%c
 channels = #osm-dev
@@ -97,7 +88,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osm-osm2pgsql-0.92.x]
 short name = osm-osm2pgsql-0.92.x
-url = git://github.com/openstreetmap/osm2pgsql.git
+url = https://github.com/openstreetmap/osm2pgsql.git
 branch = 0.92.x
 commit link = https://github.com/openstreetmap/osm2pgsql/commit/%c
 channels = #osm-dev
@@ -105,7 +96,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osm-osm2pgsql-0.90.x]
 short name = osm-osm2pgsql-0.90.x
-url = git://github.com/openstreetmap/osm2pgsql.git
+url = https://github.com/openstreetmap/osm2pgsql.git
 branch = 0.90.x
 commit link = https://github.com/openstreetmap/osm2pgsql/commit/%c
 channels = #osm-dev
@@ -113,7 +104,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osm-osm2pgsql-0.88.x]
 short name = osm-osm2pgsql-0.88.x
-url = git://github.com/openstreetmap/osm2pgsql.git
+url = https://github.com/openstreetmap/osm2pgsql.git
 branch = 0.88.x
 commit link = https://github.com/openstreetmap/osm2pgsql/commit/%c
 channels = #osm-dev
@@ -121,7 +112,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osm-mod_tile]
 short name = osm-mod_tile
-url = git://github.com/openstreetmap/mod_tile.git
+url = https://github.com/openstreetmap/mod_tile.git
 branch = master
 commit link = https://github.com/openstreetmap/mod_tile/commit/%c
 channels = #osm-dev
@@ -129,7 +120,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osm-planet-gpx-dump]
 short name = osm-planet-gpx-dump
-url = git://github.com/iandees/planet-gpx-dump.git
+url = https://github.com/iandees/planet-gpx-dump.git
 branch = master
 commit link = https://github.com/iandees/planet-gpx-dump/commit/%c
 channels = #osm-dev
@@ -137,7 +128,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osm-id]
 short name = osm-id
-url = git://github.com/openstreetmap/iD.git
+url = https://github.com/openstreetmap/iD.git
 branch = master
 commit link = https://github.com/openstreetmap/iD/commit/%c
 channels = #osm-dev
@@ -145,7 +136,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osm-maproulette]
 short name = osm-maproulette
-url = git://github.com/osmlab/maproulette.git
+url = https://github.com/osmlab/maproulette.git
 branch = master
 commit link = https://github.com/osmlab/maproulette/commit/%c
 channels = #osm-dev
@@ -153,7 +144,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osm-supybot]
 short name = osm-supybot
-url = git://github.com/iandees/supybot-plugin-osm.git
+url = https://github.com/iandees/supybot-plugin-osm.git
 commit link = https://github.com/iandees/supybot-plugin-osm/commit/%c
 branch = master
 channels = #osm-dev
@@ -161,7 +152,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osm-taginfo]
 short name = osm-taginfo
-url = git://github.com/joto/taginfo.git
+url = https://github.com/joto/taginfo.git
 commit link = https://github.com/joto/taginfo/commit/%c
 branch = master
 channels = #osm-dev
@@ -169,7 +160,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osmf-server-info]
 short name = osmf-server-info
-url = git://github.com/gravitystorm/osmf-server-info.git
+url = https://github.com/gravitystorm/osmf-server-info.git
 branch = master
 commit link = https://github.com/gravitystorm/osmf-server-info/commit/%c
 channels = #osm-dev
@@ -177,7 +168,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osm-forum]
 short name = osm-forum
-url = git://github.com/openstreetmap/openstreetmap-forum.git
+url = https://github.com/openstreetmap/openstreetmap-forum.git
 branch = openstreetmap-1.5.10
 commit link = https://github.com/openstreetmap/openstreetmap-forum/commit/%c
 channels = #osm-dev
@@ -185,7 +176,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osm-osmosis]
 short name = osm-osmosis
-url = git://github.com/openstreetmap/osmosis.git
+url = https://github.com/openstreetmap/osmosis.git
 branch = master
 commit link = https://github.com/openstreetmap/osmosis/commit/%c
 channels = #osm-dev
@@ -193,7 +184,7 @@ commit message = [%s|%b|%a] %m %l
 
 [owg-website]
 short name = owg-website
-url = git://github.com/openstreetmap/owg-website.git
+url = https://github.com/openstreetmap/owg-website.git
 branch = gh-pages
 commit link = https://github.com/openstreetmap/owg-website/commit/%c
 channels = #osm-dev
@@ -201,7 +192,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osm-josm]
 short name = osm-josm
-url = git://github.com/openstreetmap/josm.git
+url = https://github.com/openstreetmap/josm.git
 branch = master
 commit link = https://github.com/openstreetmap/josm/commit/%c
 channels = #osm-dev
@@ -209,7 +200,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osmlab-editor-layer-index]
 short name = osmlab-editor-layer-index
-url = git://github.com/osmlab/editor-layer-index.git
+url = https://github.com/osmlab/editor-layer-index.git
 branch = gh-pages
 commit link = https://github.com/osmlab/editor-layer-index/commit/%c
 channels = #osm-dev
@@ -217,7 +208,7 @@ commit message = [%s|%b|%a] %m %l
 
 [osmlab-osm-community-index]
 short name = osmlab-osm-community-index
-url = git://github.com/osmlab/osm-community-index.git
+url = https://github.com/osmlab/osm-community-index.git
 branch = master
 commit link = https://github.com/osmlab/osm-community-index/commit/%c
 channels = #osm-dev
@@ -225,8 +216,24 @@ commit message = [%s|%b|%a] %m %l
 
 [vespucci]
 short name = vespucci
-url = git://github.com/MarcusWolschon/osmeditor4android.git
+url = https://github.com/MarcusWolschon/osmeditor4android.git
 branch = master
 commit link = https://github.com//MarcusWolschon/osmeditor4android/commit/%c
 channels = #osm-dev
 commit message = [%s|%b|%a] %m %l
+
+[switch2osm]
+short name = switch2osm
+url = https://github.com/switch2osm/switch2osm.github.io.git
+branch = master
+commit link = https://github.com/switch2osm/switch2osm.github.io/commit/%c
+channels = #osm-dev
+commit message = [%s|%b|%a] %m %l
+
+[simon-openinghoursparser]
+short name = simon-openinghoursparser
+url = https://github.com/simonpoole/OpeningHoursParser.git
+branch = master
+commit link = https://github.com/simonpoole/OpeningHoursParser/commit/%c
+channels = #osm-dev
+commit message = [%s|%b|%a] %m %l
index fe3c63eb6d2b23a545450497e49cb1ac8e734292..bf7cd709dde36e61a1e239437c81df1583cb7b83 100644 (file)
@@ -58,7 +58,7 @@ supybot.networks.oftc.password:
 #
 # Default value: 
 ###
-supybot.networks.oftc.servers: irc.oftc.net:6667
+supybot.networks.oftc.servers: irc.oftc.net:6697
 
 ###
 # Determines what channels the bot will join only on oftc.
@@ -80,7 +80,7 @@ supybot.networks.oftc.channels.key:
 #
 # Default value: False
 ###
-supybot.networks.oftc.ssl: False
+supybot.networks.oftc.ssl: True
 
 ###
 # Determines how timestamps printed for human reading should be
@@ -637,6 +637,13 @@ supybot.directories.data: /var/lib/supybot/data
 ###
 supybot.directories.data.tmp: /var/lib/supybot/data/tmp
 
+###
+# Determines what directory files of the web server (templates, custom images, ...) are put into.
+#
+# Default value: web
+###
+supybot.directories.data.web: /var/lib/supybot/data/web
+
 ###
 # Determines what directory backup data is put into.
 #
@@ -887,7 +894,6 @@ supybot.plugins.Services.NickServ: NickServ
 #
 # Default value: 
 ###
-supybot.plugins.Services.NickServ.password: <%= @passwords["nickserv"] %>
 supybot.plugins.Services.NickServ.password.osmbot: <%= @passwords["nickserv"] %>
 
 ###
@@ -1062,6 +1068,15 @@ supybot.databases.types.cdb: True
 ###
 supybot.databases.types.cdb.maximumModifications: 0.5
 
+###
+# Determines whether server certificates will be verified, which
+# checks whether the server certificate is signed by a known certificate
+# authority, and aborts the connection if it is not.
+#
+# Default value: False
+###
+supybot.protocols.ssl.verifyCertificates: True
+
 ###
 # Determines what will be used as the default banmask style.
 #
index 3a380b93fa2e2368ce7e57f3ad9a3b6512cca1dc..c87125ac31767544ce6007a5e40d90cf06076268 100644 (file)
@@ -6,4 +6,5 @@ description       "Installs and configures servers for switch2osm"
 
 version           "1.0.0"
 supports          "ubuntu"
-depends           "wordpress"
+depends           "apache"
+depends           "git"
index 00fcd95fb0a15c008efeb94ff4e873c0fb380159..c0a3da3cbf87aa9165c268e93b7b0c876f9a6a84 100644 (file)
 # limitations under the License.
 #
 
-include_recipe "wordpress"
+include_recipe "apache"
+include_recipe "git"
 
-passwords = data_bag_item("switch2osm", "passwords")
+package %w[
+  gcc
+  g++
+  make
+  ruby
+  ruby-dev
+  libssl-dev
+  zlib1g-dev
+  pkg-config
+]
 
-wordpress_site "switch2osm.org" do
-  aliases ["www.switch2osm.org", "switch2osm.com", "www.switch2osm.com"]
-  directory "/srv/switch2osm.org"
-  database_name "switch2osm-blog"
-  database_user "switch2osm-user"
-  database_password passwords["switch2osm-user"]
-end
-
-wordpress_theme "switch2osm.org-picolight" do
-  theme "picolight"
-  site "switch2osm.org"
-  repository "git://github.com/Firefishy/picolight-s2o.git"
-  revision "master"
-end
+apache_module "expires"
+apache_module "rewrite"
 
-wordpress_plugin "switch2osm.org-sitepress-multilingual-cms" do
-  plugin "sitepress-multilingual-cms"
-  site "switch2osm.org"
-  repository "https://git.openstreetmap.org/private/sitepress-multilingual-cms.git"
+gem_package "bundler" do
+  version "1.17.3"
 end
 
-wordpress_plugin "switch2osm.org-wpml-cms-nav" do
-  plugin "wpml-cms-nav"
-  site "switch2osm.org"
-  repository "https://git.openstreetmap.org/private/wpml-cms-nav.git"
+git "/srv/switch2osm.org" do
+  action :sync
+  repository "https://github.com/switch2osm/switch2osm.github.io.git"
+  depth 1
+  user "root"
+  group "root"
+  notifies :run, "execute[/srv/switch2osm.org/Gemfile]"
 end
 
-wordpress_plugin "switch2osm.org-wpml-sticky-links" do
-  plugin "wpml-sticky-links"
-  site "switch2osm.org"
-  repository "https://git.openstreetmap.org/private/wpml-sticky-links.git"
+directory "/srv/switch2osm.org/_site" do
+  mode "755"
+  owner "nobody"
+  group "nogroup"
 end
 
-wordpress_plugin "switch2osm.org-wpml-string-translation" do
-  plugin "wpml-string-translation"
-  site "switch2osm.org"
-  repository "https://git.openstreetmap.org/private/wpml-string-translation.git"
+# Workaround https://github.com/jekyll/jekyll/issues/7804
+# by creating a .jekyll-cache folder
+directory "/srv/switch2osm.org/.jekyll-cache" do
+  mode "755"
+  owner "nobody"
+  group "nogroup"
 end
 
-wordpress_plugin "switch2osm.org-wpml-translation-analytics" do
-  plugin "wpml-translation-analytics"
-  site "switch2osm.org"
-  repository "https://git.openstreetmap.org/private/wpml-translation-analytics.git"
+execute "/srv/switch2osm.org/Gemfile" do
+  action :nothing
+  command "bundle install --deployment"
+  cwd "/srv/switch2osm.org"
+  user "root"
+  group "root"
+  notifies :run, "execute[/srv/switch2osm.org]"
 end
 
-wordpress_plugin "switch2osm.org-wpml-translation-management" do
-  plugin "wpml-translation-management"
-  site "switch2osm.org"
-  repository "https://git.openstreetmap.org/private/wpml-translation-management.git"
+execute "/srv/switch2osm.org" do
+  action :nothing
+  command "bundle exec jekyll build --trace --config _config.yml,_config_osm.yml"
+  cwd "/srv/switch2osm.org"
+  user "nobody"
+  group "nogroup"
 end
 
-wordpress_plugin "switch2osm.org-wpml-xliff" do
-  plugin "wpml-xliff"
-  site "switch2osm.org"
-  repository "https://git.openstreetmap.org/private/wpml-xliff.git"
+ssl_certificate "switch2osm.org" do
+  domains ["switch2osm.org",
+           "www.switch2osm.org", "switch2osm.com", "www.switch2osm.com"]
+  notifies :reload, "service[apache2]"
 end
 
-template "/etc/cron.daily/switch2osm-backup" do
-  source "backup.cron.erb"
-  owner "root"
-  group "root"
-  mode 0o750
-  variables :passwords => passwords
+apache_site "switch2osm.org" do
+  template "apache.erb"
+  directory "/srv/switch2osm.org/_site"
 end
diff --git a/cookbooks/switch2osm/templates/default/apache.erb b/cookbooks/switch2osm/templates/default/apache.erb
new file mode 100644 (file)
index 0000000..e355c81
--- /dev/null
@@ -0,0 +1,41 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:443>
+   ServerName <%= @name %>
+   ServerAlias www.switch2osm.org
+   ServerAlias switch2osm.com
+   ServerAlias www.switch2osm.com
+   ServerAdmin webmaster@openstreetmap.org
+
+   CustomLog /var/log/apache2/<%= @name %>-access.log combined
+   ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+   SSLEngine on
+   SSLCertificateFile /etc/ssl/certs/<%= @name %>.pem
+   SSLCertificateKeyFile /etc/ssl/private/<%= @name %>.key
+
+   DocumentRoot <%= @directory %>
+
+   ErrorDocument 404 /404.html
+
+   ExpiresActive On
+   ExpiresDefault "access plus 10 minutes"
+</VirtualHost>
+
+<VirtualHost *:80>
+   ServerName <%= @name %>
+   ServerAlias www.switch2osm.org
+   ServerAlias switch2osm.com
+   ServerAlias www.switch2osm.com
+   ServerAdmin webmaster@openstreetmap.org
+
+   CustomLog /var/log/apache2/<%= @name %>-access.log combined
+   ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+   RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
+   RedirectPermanent / https://<%= @name %>/
+</VirtualHost>
+
+<Directory <%= @directory %>>
+   Require all granted
+</Directory>
diff --git a/cookbooks/switch2osm/templates/default/backup.cron.erb b/cookbooks/switch2osm/templates/default/backup.cron.erb
deleted file mode 100644 (file)
index 54717f4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-
-# DO NOT EDIT - This file is being maintained by Chef
-
-T=$(mktemp -d -t -p /var/tmp switch2osm.XXXXXXXXXX)
-D=$(date +%Y-%m-%d)
-B=switch2osm-$D.tar.gz
-
-mkdir $T/switch2osm-$D
-echo '[mysqldump]' > $T/mysqldump.opts
-echo 'user=switch2osm-user' >> $T/mysqldump.opts
-echo 'password=<%= @passwords["switch2osm-user"] %>' >> $T/mysqldump.opts
-mysqldump --defaults-file=$T/mysqldump.opts --opt switch2osm-blog > $T/switch2osm-$D/switch2osm-blog.sql
-ln -s /srv/switch2osm.org $T/switch2osm-$D/www
-
-export GZIP="--rsyncable -9"
-
-nice tar --create --gzip --dereference --directory=$T --file=$T/$B switch2osm-$D
-nice rsync --preallocate --fuzzy $T/$B backup::backup
-
-rm -rf $T
diff --git a/cookbooks/sysctl/attributes/default.rb b/cookbooks/sysctl/attributes/default.rb
new file mode 100644 (file)
index 0000000..5c16360
--- /dev/null
@@ -0,0 +1 @@
+default[:sysctl] = {}
index 14295b37726baba083b2479cdc5f4b4c5f73955a..f16537c5185c277d12897f8424bf8b6cf58575d9 100644 (file)
 # limitations under the License.
 #
 
-if node[:virtualization][:role] == "guest" &&
-   node[:virtualization][:system] == "lxd"
-  file "/etc/sysctl.d/60-chef.conf" do
-    action :delete
-  end
-else
-  package "procps"
+file "/etc/sysctl.d/60-chef.conf" do
+  action :delete
+end
 
-  directory "/etc/sysctl.d" do
-    owner "root"
-    group "root"
-    mode 0o755
-  end
+if node[:virtualization][:role] != "guest" ||
+   (node[:virtualization][:system] != "lxc" &&
+    node[:virtualization][:system] != "lxd" &&
+    node[:virtualization][:system] != "openvz")
+  keys = []
 
-  execute "sysctl" do
-    action :nothing
-    command "/sbin/sysctl -p /etc/sysctl.d/60-chef.conf"
-  end
+  Dir.new("/etc/sysctl.d").each_entry do |file|
+    next unless file =~ /^99-chef-(.*)\.conf$/
 
-  template "/etc/sysctl.d/60-chef.conf" do
-    source "chef.conf.erb"
-    owner "root"
-    group "root"
-    mode 0o644
-    notifies :run, "execute[sysctl]"
+    keys.push(Regexp.last_match(1))
   end
 
   node[:sysctl].each_value do |group|
     group[:parameters].each do |key, value|
-      sysctl_file = "/proc/sys/#{key.tr('.', '/')}"
-
-      file sysctl_file do
-        content "#{value}\n"
-        atomic_update false
-        ignore_failure true
+      sysctl key do
+        value value
+        # comment group[:comment]
       end
+
+      keys.delete(key)
+    end
+  end
+
+  keys.each do |key|
+    sysctl key do
+      action :remove
     end
   end
 end
diff --git a/cookbooks/sysctl/templates/default/chef.conf.erb b/cookbooks/sysctl/templates/default/chef.conf.erb
deleted file mode 100644 (file)
index 991664f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-<% node[:sysctl].each do |name,group| -%>
-
-# <%= group[:comment] %>
-<% group[:parameters].each do |key,value| -%>
-<%= key %> = <%= value %>
-<% end -%>
-<% end -%>
index c34a16989baafb79d769a6d5f92e708ab75b6a98..6e2dac1f5ba0dcf011bcaaa03861865fa0da1e01 100644 (file)
@@ -30,11 +30,11 @@ else
     supports :status => false, :restart => true, :reload => false
   end
 
-  template "/etc/sysfs.conf" do
+  template "/etc/sysfs.d/99-chef.conf" do
     source "sysfs.conf.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     notifies :restart, "service[sysfsutils]"
   end
 
index 139f4b8db6cbdad2e7176f236c35e20cca2ae954..29bbfa51c1782a664e8d809cddf76812871df5a2 100644 (file)
@@ -20,7 +20,7 @@
 default_action :create
 
 property :path, String, :name_property => true
-property :description, String, :required => true
+property :description, String, :required => [:create]
 property :after, [String, Array]
 property :wants, [String, Array]
 property :path_exists, [String, Array]
@@ -29,7 +29,7 @@ property :path_changed, [String, Array]
 property :path_modified, [String, Array]
 property :directory_not_empty, [String, Array]
 property :unit, String
-property :make_directory, [TrueClass, FalseClass]
+property :make_directory, [true, false]
 property :directory_mode, Integer
 
 action :create do
@@ -40,7 +40,7 @@ action :create do
     source "path.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables path_variables
   end
 
index 3132c63cdcba5829061cb3aef35c10fd986797e1..62c9596921cf4c04972ec49cff4ae377f367e6b0 100644 (file)
@@ -22,7 +22,10 @@ default_action :create
 property :service, String, :name_property => true
 property :dropin, String
 property :description, String
+property :condition_path_exists, [String, Array]
+property :condition_path_exists_glob, [String, Array]
 property :after, [String, Array]
+property :conflicts, [String, Array]
 property :wants, [String, Array]
 property :type, String, :is => %w[simple forking oneshot dbus notify idle]
 property :limit_nofile, Integer
@@ -52,15 +55,24 @@ property :standard_error, String,
 property :success_exit_status, [Integer, String, Array]
 property :restart, String,
          :is => %w[on-success on-failure on-abnormal on-watchdog on-abort always]
-property :private_tmp, [TrueClass, FalseClass]
-property :private_devices, [TrueClass, FalseClass]
-property :private_network, [TrueClass, FalseClass]
+property :private_tmp, [true, false]
+property :private_devices, [true, false]
+property :private_network, [true, false]
 property :protect_system, [TrueClass, FalseClass, String]
 property :protect_home, [TrueClass, FalseClass, String]
+property :read_write_paths, [String, Array]
+property :read_only_paths, [String, Array]
+property :inaccessible_paths, [String, Array]
 property :restrict_address_families, [String, Array]
-property :no_new_privileges, [TrueClass, FalseClass]
+property :no_new_privileges, [true, false]
+property :tasks_max, Integer
 property :timeout_sec, Integer
 property :pid_file, String
+property :nice, Integer
+property :io_scheduling_class, [Integer, String]
+property :io_scheduling_priority, Integer
+property :kill_mode, String,
+         :is => %w[control-group process mixed none]
 
 action :create do
   service_variables = new_resource.to_hash
@@ -75,7 +87,7 @@ action :create do
       source "environment.erb"
       owner "root"
       group "root"
-      mode 0o640
+      mode "640"
       variables :environment => new_resource.environment_file
     end
 
@@ -86,7 +98,7 @@ action :create do
     directory dropin_directory do
       owner "root"
       group "root"
-      mode 0o755
+      mode "755"
     end
   end
 
@@ -95,7 +107,7 @@ action :create do
     source "service.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables service_variables
     notifies :run, "execute[systemctl-reload]"
   end
index b33cff2d0b84d2581af5ab3f2f250658023853cb..7dc4cab6544a69b8be0dbd93c660e0d39166a9cf 100644 (file)
@@ -20,7 +20,7 @@
 default_action :create
 
 property :timer, String, :name_property => true
-property :description, String, :required => true
+property :description, String, :required => [:create]
 property :after, [String, Array]
 property :wants, [String, Array]
 property :on_active_sec, [Integer, String]
@@ -32,9 +32,9 @@ property :on_calendar, String
 property :accuracy_sec, [Integer, String]
 property :randomized_delay_sec, [Integer, String]
 property :unit, String
-property :persistent, [TrueClass, FalseClass]
-property :wake_system, [TrueClass, FalseClass]
-property :remain_after_elapse, [TrueClass, FalseClass]
+property :persistent, [true, false]
+property :wake_system, [true, false]
+property :remain_after_elapse, [true, false]
 
 action :create do
   timer_variables = new_resource.to_hash
@@ -44,7 +44,7 @@ action :create do
     source "timer.erb"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
     variables timer_variables
   end
 
index 8c21b6b6ff3462a79f2ae0c386627946cde88309..38538e15f22bd0aaace63faa7fd48a56eb85f964 100644 (file)
@@ -19,7 +19,7 @@
 
 default_action :create
 
-property :type, String, :required => true
+property :type, String, :required => [:create]
 property :path, String, :name_property => true
 property :mode, String, :default => "-"
 property :owner, String, :default => "-"
@@ -33,8 +33,8 @@ action :create do
     source "tmpfile.erb"
     owner "root"
     group "root"
-    mode 0o644
-    variables new_resource.to_hash
+    mode "644"
+    variables new_resource.to_hash.merge(:path => new_resource.path)
   end
 
   execute "systemd-tmpfiles" do
index ed117c24e51932c849cce0ed0c0ea42792c4798c..eff7b83084cf19ce694b5a30903f45020b370666 100644 (file)
@@ -4,9 +4,18 @@
 <% if @description -%>
 Description=<%= @description %>
 <% end -%>
+<% if @condition_path_exists -%>
+ConditionPathExists=<%= Array(@condition_path_exists).join(" ") %>
+<% end -%>
+<% if @condition_path_exists_glob -%>
+ConditionPathExistsGlob=<%= Array(@condition_path_exists_glob).join(" ") %>
+<% end -%>
 <% if @after -%>
 After=<%= Array(@after).join(" ") %>
 <% end -%>
+<% if @conflicts -%>
+Conflicts=<%= Array(@conflicts).join(" ") %>
+<% end -%>
 <% if @wants -%>
 Wants=<%= Array(@wants).join(" ") %>
 <% end -%>
@@ -49,18 +58,33 @@ Group=<%= @group %>
 WorkingDirectory=<%= @working_directory %>
 <% end -%>
 <% if @exec_start_pre -%>
+<% if @dropin -%>
+ExecStartPre=
+<% end -%>
 ExecStartPre=<%= @exec_start_pre %>
 <% end -%>
 <% if @exec_start -%>
+<% if @dropin -%>
+ExecStart=
+<% end -%>
 ExecStart=<%= @exec_start %>
 <% end -%>
 <% if @exec_start_post -%>
+<% if @dropin -%>
+ExecStartPost=
+<% end -%>
 ExecStartPost=<%= @exec_start_post %>
 <% end -%>
 <% if @exec_stop -%>
+<% if @dropin -%>
+ExecStop=
+<% end -%>
 ExecStop=<%= @exec_stop %>
 <% end -%>
 <% if @exec_reload -%>
+<% if @dropin -%>
+ExecReload=
+<% end -%>
 ExecReload=<%= @exec_reload %>
 <% end -%>
 <% if @runtime_directory -%>
@@ -93,12 +117,24 @@ ProtectSystem=<%= @protect_system %>
 <% if @protect_home -%>
 ProtectHome=<%= @protect_home %>
 <% end -%>
+<% if @read_write_paths -%>
+ReadWritePaths=<%= Array(@read_write_paths).join(" ") %>
+<% end -%>
+<% if @read_only_paths -%>
+ReadOnlyPaths=<%= Array(@read_only_paths).join(" ") %>
+<% end -%>
+<% if @inaccessible_paths -%>
+InaccessiblePaths=<%= Array(@inaccessible_paths).join(" ") %>
+<% end -%>
 <% if @restrict_address_families -%>
 RestrictAddressFamilies=<%= Array(@restrict_address_families).join(" ") %>
 <% end -%>
 <% if @no_new_privileges -%>
 NoNewPrivileges=<%= @no_new_privileges %>
 <% end -%>
+<% if @tasks_max -%>
+TasksMax=<%= @tasks_max %>
+<% end -%>
 <% if @success_exit_status -%>
 SuccessExitStatus=<%= Array(@success_exit_status).join(" ") %>
 <% end -%>
@@ -111,6 +147,18 @@ TimeoutSec=<%= @timeout_sec %>
 <% if @pid_file -%>
 PIDFile=<%= @pid_file %>
 <% end -%>
+<% if @nice -%>
+Nice=<%= @nice %>
+<% end -%>
+<% if @io_scheduling_class -%>
+IOSchedulingClass=<%= @io_scheduling_class %>
+<% end -%>
+<% if @io_scheduling_priority -%>
+IOSchedulingPriority=<%= @io_scheduling_priority %>
+<% end -%>
+<% if @kill_mode -%>
+KillMode=<%= @kill_mode %>
+<% end -%>
 <% unless @dropin -%>
 
 [Install]
index c7098b77b7b58f17aa1e44917b5fae47b68c0acb..266ac250a6a7cd60aeb596bb4c5d4e2b1487a1f7 100644 (file)
@@ -1 +1,3 @@
 default[:taginfo][:sites] = []
+
+default[:accounts][:users][:taginfo][:status] = :role
index 37794a28ee4df3440679a4add44add9d696ec4a2..3fdbc2f51086bf2ce992c0314cee6ad9639f2c83 100644 (file)
@@ -6,6 +6,7 @@ description       "Installs and configures taginfo"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
 depends           "passenger"
 depends           "git"
index 4289c0042d3b7f24b557959cd1055622421617a7..5383415217ea5f543e05dfe7f37e2f436c0628d7 100644 (file)
@@ -19,6 +19,7 @@
 
 require "json"
 
+include_recipe "accounts"
 include_recipe "apache"
 include_recipe "passenger"
 include_recipe "git"
@@ -42,6 +43,7 @@ package %w[
 
 package %w[
   sqlite3
+  sqlite3-pcre
   osmium-tool
   pyosmium
   curl
@@ -54,6 +56,7 @@ package "ruby#{ruby_version}"
 
 gem_package "bundler#{ruby_version}" do
   package_name "bundler"
+  version "~> 1.16.2"
   gem_binary "gem#{ruby_version}"
   options "--format-executable"
 end
@@ -65,14 +68,14 @@ apache_module "headers"
 directory "/var/log/taginfo" do
   owner "taginfo"
   group "taginfo"
-  mode 0o755
+  mode "755"
 end
 
 template "/etc/sudoers.d/taginfo" do
   source "sudoers.erb"
   owner "root"
   group "root"
-  mode 0o440
+  mode "440"
 end
 
 node[:taginfo][:sites].each do |site|
@@ -87,19 +90,47 @@ node[:taginfo][:sites].each do |site|
   directory "/var/log/taginfo/#{site_name}" do
     owner "taginfo"
     group "taginfo"
-    mode 0o755
+    mode "755"
   end
 
   directory directory do
     owner "taginfo"
     group "taginfo"
-    mode 0o755
+    mode "755"
+  end
+
+  git "#{directory}/taginfo-tools" do
+    action :sync
+    repository "https://github.com/taginfo/taginfo-tools.git"
+    revision "osmorg-taginfo-live"
+    depth 1
+    enable_submodules true
+    user "taginfo"
+    group "taginfo"
+  end
+
+  directory "#{directory}/build" do
+    owner "taginfo"
+    group "taginfo"
+    mode "755"
+  end
+
+  execute "compile_taginfo_tools" do
+    action :nothing
+    user "taginfo"
+    group "taginfo"
+    cwd "#{directory}/build"
+    command "cmake #{directory}/taginfo-tools -DCMAKE_BUILD_TYPE=Release && make"
+    subscribes :run, "apt_package[libprotozero-dev]"
+    subscribes :run, "apt_package[libosmium2-dev]"
+    subscribes :run, "git[#{directory}/taginfo-tools]"
   end
 
   git "#{directory}/taginfo" do
     action :sync
-    repository "git://github.com/taginfo/taginfo.git"
+    repository "https://github.com/taginfo/taginfo.git"
     revision "osmorg-taginfo-live"
+    depth 1
     user "taginfo"
     group "taginfo"
   end
@@ -116,10 +147,11 @@ node[:taginfo][:sites].each do |site|
     settings["logging"]["directory"] = "/var/log/taginfo/#{site_name}"
     settings["opensearch"]["shortname"] = "Taginfo"
     settings["opensearch"]["contact"] = "webmaster@openstreetmap.org"
+    settings["paths"]["bin_dir"] = "#{directory}/build/src"
     settings["sources"]["download"] = ""
-    settings["sources"]["create"] = "db languages projects wiki"
-    settings["sources"]["db"]["planetfile"] = "/var/lib/planet/planet.pbf"
-    settings["sources"]["db"]["bindir"] = "#{directory}/taginfo/tagstats"
+    settings["sources"]["create"] = "db languages projects wiki chronology"
+    settings["sources"]["db"]["planetfile"] = "/var/lib/planet/planet.osh.pbf"
+    settings["sources"]["chronology"]["osm_history_file"] = "/var/lib/planet/planet.osh.pbf"
     settings["tagstats"]["geodistribution"] = "DenseMmapArray"
 
     JSON.pretty_generate(settings)
@@ -128,23 +160,11 @@ node[:taginfo][:sites].each do |site|
   file "#{directory}/taginfo-config.json" do
     owner "taginfo"
     group "taginfo"
-    mode 0o644
+    mode "644"
     content settings
     notifies :restart, "service[apache2]"
   end
 
-  execute "#{directory}/taginfo/tagstats/Makefile" do
-    action :nothing
-    command "make"
-    cwd "#{directory}/taginfo/tagstats"
-    user "taginfo"
-    group "taginfo"
-    subscribes :run, "apt_package[libprotozero-dev]"
-    subscribes :run, "apt_package[libosmium2-dev]"
-    subscribes :run, "git[#{directory}/taginfo]"
-    notifies :restart, "service[apache2]"
-  end
-
   execute "#{directory}/taginfo/Gemfile" do
     action :nothing
     command "bundle#{ruby_version} install"
@@ -160,7 +180,7 @@ node[:taginfo][:sites].each do |site|
     directory "#{directory}/#{dir}" do
       owner "taginfo"
       group "taginfo"
-      mode 0o755
+      mode "755"
     end
   end
 
@@ -168,7 +188,7 @@ node[:taginfo][:sites].each do |site|
     source "update.erb"
     owner "taginfo"
     group "taginfo"
-    mode 0o755
+    mode "755"
     variables :name => site_name, :directory => directory
   end
 
@@ -192,6 +212,6 @@ template "/usr/local/bin/taginfo-update" do
   source "taginfo-update.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   variables :sites => node[:taginfo][:sites]
 end
index 7ef34a9580b7f808f6059c2901e8ed15870923c1..7ad888fd0f45b232429a8b3ff0ac2375754cd9dc 100644 (file)
@@ -1,2 +1,16 @@
+default[:tile][:database][:cluster] = "12/main"
+default[:tile][:database][:postgis] = "3"
+default[:tile][:database][:node_file] = "/store/database/nodes"
+default[:tile][:database][:multi_geometry] = true
+default[:tile][:database][:hstore] = true
+default[:tile][:database][:style_file] = nil
+default[:tile][:database][:tag_transform_script] = nil
+
+default[:tile][:replication][:url] = "https://planet.osm.org/replication/minute/"
+
 default[:tile][:data] = {}
 default[:tile][:styles] = {}
+
+default[:postgresql][:versions] |= [node[:tile][:database][:cluster].split("/").first]
+
+default[:accounts][:users][:tile][:status] = :role
index 99516431402a9ba17423523cfbe19b2bcf7dba53..30b41c3436c705890041272b01c19ff55ec4d891 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 """
 Expire meta tiles from a OSM change file by resetting their modified time.
 """
@@ -12,8 +12,7 @@ EXPIRY_TIME = 946681200 # 2000-01-01 00:00:00
 # width/height of the spherical mercator projection
 SIZE = 40075016.6855784
 
-proj_wsg84 = pyproj.Proj(init='epsg:4326')
-proj_merc = pyproj.Proj(init='epsg:3857')
+proj_transformer = pyproj.Transformer.from_crs('epsg:4326', 'epsg:3857', always_xy = True)
 
 class TileCollector(o.SimpleHandler):
 
@@ -29,7 +28,7 @@ class TileCollector(o.SimpleHandler):
             return
 
         lat = max(-85, min(85.0, location.lat))
-        x, y = pyproj.transform(proj_wsg84, proj_merc, location.lon, lat)
+        x, y = proj_transformer.transform(location.lon, lat)
 
         # renormalise into unit space [0,1]
         x = 0.5 + x / SIZE
index 27b042b5cec16967462ab011cf4b47320fbc14c4..975e1cb0d9a56a11d5843a5bc851bd8ed2f6b0ca 100644 (file)
Binary files a/cookbooks/tile/files/default/html/favicon.ico and b/cookbooks/tile/files/default/html/favicon.ico differ
index 8c995d11e7734f97109a290d02c57ea7e34a0a69..bd84ccec03b2eec46ca135d89454c9b915497e6a 100644 (file)
@@ -6,10 +6,13 @@ description       "Installs and configures tile servers"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
 depends           "git"
+depends           "munin"
 depends           "nodejs"
 depends           "postgresql"
+depends           "prometheus"
 depends           "python"
 depends           "systemd"
 depends           "tools"
index ead3638aacb063c51f14cffedd0f579e7923eeb3..7d5052fc2822b388146bd667b0c3d27093df7657 100644 (file)
 # limitations under the License.
 #
 
+include_recipe "accounts"
 include_recipe "apache"
 include_recipe "git"
+include_recipe "munin"
 include_recipe "nodejs"
 include_recipe "postgresql"
+include_recipe "prometheus"
 include_recipe "python"
 include_recipe "tools"
 
@@ -43,7 +46,14 @@ ssl_certificate node[:fqdn] do
   notifies :reload, "service[apache2]"
 end
 
+remote_file "#{Chef::Config[:file_cache_path]}/fastly-ip-list.json" do
+  source "https://api.fastly.com/public-ip-list"
+  compile_time true
+  ignore_failure true
+end
+
 tilecaches = search(:node, "roles:tilecache").sort_by { |n| n[:hostname] }
+fastlyips = JSON.parse(IO.read("#{Chef::Config[:file_cache_path]}/fastly-ip-list.json"))
 
 apache_site "default" do
   action [:disable]
@@ -51,20 +61,20 @@ end
 
 apache_site "tile.openstreetmap.org" do
   template "apache.erb"
-  variables :caches => tilecaches
+  variables :caches => tilecaches, :fastly => fastlyips["addresses"]
 end
 
 template "/etc/logrotate.d/apache2" do
   source "logrotate.apache.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 directory "/srv/tile.openstreetmap.org" do
   owner "tile"
   group "tile"
-  mode 0o755
+  mode "755"
 end
 
 package "renderd"
@@ -77,6 +87,7 @@ systemd_service "renderd" do
   exec_start "/usr/bin/renderd -f"
   runtime_directory "renderd"
   standard_error "null"
+  limit_nofile 4096
   private_tmp true
   private_devices true
   private_network true
@@ -94,14 +105,14 @@ end
 directory "/srv/tile.openstreetmap.org/tiles" do
   owner "tile"
   group "tile"
-  mode 0o755
+  mode "755"
 end
 
 template "/etc/renderd.conf" do
   source "renderd.conf.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
   notifies :reload, "service[apache2]"
   notifies :restart, "service[renderd]"
 end
@@ -110,26 +121,28 @@ remote_directory "/srv/tile.openstreetmap.org/html" do
   source "html"
   owner "tile"
   group "tile"
-  mode 0o755
+  mode "755"
   files_owner "tile"
   files_group "tile"
-  files_mode 0o644
+  files_mode "644"
 end
 
 template "/srv/tile.openstreetmap.org/html/index.html" do
   source "index.html.erb"
   owner "tile"
   group "tile"
-  mode 0o644
+  mode "644"
 end
 
 package %w[
-  python-cairo
-  python-mapnik
-  python-setuptools
+  python3-cairo
+  python3-mapnik
+  python3-setuptools
 ]
 
-python_package "pyotp"
+python_package "pyotp" do
+  python_version "3"
+end
 
 package %w[
   fonts-noto-cjk
@@ -145,21 +158,21 @@ package %w[
     source "https://github.com/googlei18n/noto-fonts/raw/master/hinted/#{font}"
     owner "root"
     group "root"
-    mode 0o644
+    mode "644"
   end
 end
 
 directory "/srv/tile.openstreetmap.org/cgi-bin" do
   owner "tile"
   group "tile"
-  mode 0o755
+  mode "755"
 end
 
 template "/srv/tile.openstreetmap.org/cgi-bin/export" do
   source "export.erb"
   owner "tile"
   group "tile"
-  mode 0o755
+  mode "755"
   variables :blocks => blocks, :totp_key => web_passwords["totp_key"]
 end
 
@@ -167,20 +180,20 @@ template "/srv/tile.openstreetmap.org/cgi-bin/debug" do
   source "debug.erb"
   owner "tile"
   group "tile"
-  mode 0o755
+  mode "755"
 end
 
 template "/etc/cron.hourly/export" do
   source "export.cron.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 directory "/srv/tile.openstreetmap.org/data" do
   owner "tile"
   group "tile"
-  mode 0o755
+  mode "755"
 end
 
 package "mapnik-utils"
@@ -195,7 +208,7 @@ node[:tile][:data].each_value do |data|
     directory directory do
       owner "tile"
       group "tile"
-      mode 0o755
+      mode "755"
     end
   else
     directory = "/srv/tile.openstreetmap.org/data"
@@ -250,7 +263,7 @@ node[:tile][:data].each_value do |data|
     source url
     owner "tile"
     group "tile"
-    mode 0o644
+    mode "644"
     backup false
     notifies :run, "execute[#{file}]", :immediately
     notifies :restart, "service[renderd]"
@@ -258,12 +271,13 @@ node[:tile][:data].each_value do |data|
 end
 
 nodejs_package "carto"
-nodejs_package "millstone"
 
 systemd_service "update-lowzoom@" do
   description "Low zoom tile update service for %i layer"
+  conflicts "render-lowzoom.service"
   user "tile"
   exec_start "/bin/bash /usr/local/bin/update-lowzoom-%i"
+  runtime_directory "update-lowzoom-%i"
   private_tmp true
   private_devices true
   private_network true
@@ -276,7 +290,7 @@ end
 directory "/srv/tile.openstreetmap.org/styles" do
   owner "tile"
   group "tile"
-  mode 0o755
+  mode "755"
 end
 
 node[:tile][:styles].each do |name, details|
@@ -287,7 +301,7 @@ node[:tile][:styles].each do |name, details|
     source "update-lowzoom.erb"
     owner "root"
     group "root"
-    mode 0o755
+    mode "755"
     variables :style => name
   end
 
@@ -299,21 +313,21 @@ node[:tile][:styles].each do |name, details|
   directory tile_directory do
     owner "tile"
     group "tile"
-    mode 0o755
+    mode "755"
   end
 
   details[:tile_directories].each do |directory|
     directory directory[:name] do
       owner "www-data"
       group "www-data"
-      mode 0o755
+      mode "755"
     end
 
     directory[:min_zoom].upto(directory[:max_zoom]) do |zoom|
       directory "#{directory[:name]}/#{zoom}" do
         owner "www-data"
         group "www-data"
-        mode 0o755
+        mode "755"
       end
 
       link "#{tile_directory}/#{zoom}" do
@@ -328,7 +342,7 @@ node[:tile][:styles].each do |name, details|
     action :create_if_missing
     owner "tile"
     group "tile"
-    mode 0o444
+    mode "444"
   end
 
   git style_directory do
@@ -360,7 +374,6 @@ end
 postgresql_version = node[:tile][:database][:cluster].split("/").first
 postgis_version = node[:tile][:database][:postgis]
 
-package "postgis"
 package "postgresql-#{postgresql_version}-postgis-#{postgis_version}"
 
 postgresql_user "jburgess" do
@@ -394,6 +407,7 @@ end
 postgresql_extension "hstore" do
   cluster node[:tile][:database][:cluster]
   database "gis"
+  only_if { node[:tile][:database][:hstore] }
 end
 
 %w[geography_columns planet_osm_nodes planet_osm_rels planet_osm_ways raster_columns raster_overviews spatial_ref_sys].each do |table|
@@ -414,21 +428,52 @@ end
   end
 end
 
+package %w[
+  gdal-bin
+  python3-yaml
+  python3-psycopg2
+]
+
+if node[:tile][:database][:external_data_script]
+  execute node[:tile][:database][:external_data_script] do
+    command node[:tile][:database][:external_data_script]
+    cwd "/srv/tile.openstreetmap.org"
+    user "tile"
+    group "tile"
+  end
+
+  Array(node[:tile][:database][:external_data_tables]).each do |table|
+    postgresql_table table do
+      cluster node[:tile][:database][:cluster]
+      database "gis"
+      owner "tile"
+      permissions "tile" => :all, "www-data" => :select
+    end
+  end
+end
+
 postgresql_munin "gis" do
   cluster node[:tile][:database][:cluster]
   database "gis"
 end
 
-file node[:tile][:node_file] do
+directory File.dirname(node[:tile][:database][:node_file]) do
+  owner "root"
+  group "root"
+  mode "755"
+  recursive true
+end
+
+file node[:tile][:database][:node_file] do
   owner "tile"
   group "www-data"
-  mode 0o660
+  mode "660"
 end
 
 directory "/var/log/tile" do
   owner "tile"
   group "tile"
-  mode 0o755
+  mode "755"
 end
 
 package %w[
@@ -436,43 +481,44 @@ package %w[
   ruby
   osmium-tool
   pyosmium
-  python-pyproj
+  python3-pyproj
 ]
 
 remote_directory "/usr/local/bin" do
   source "bin"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   files_owner "root"
   files_group "root"
-  files_mode 0o755
+  files_mode "755"
 end
 
 template "/usr/local/bin/expire-tiles" do
   source "expire-tiles.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 directory "/var/lib/replicate" do
   owner "tile"
   group "tile"
-  mode 0o755
+  mode "755"
 end
 
 directory "/var/lib/replicate/expire-queue" do
   owner "tile"
   group "www-data"
-  mode 0o775
+  mode "775"
 end
 
 template "/usr/local/bin/replicate" do
   source "replicate.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
+  variables :postgresql_version => postgresql_version.to_f
 end
 
 systemd_service "expire-tiles" do
@@ -522,18 +568,19 @@ template "/etc/logrotate.d/replicate" do
   source "replicate.logrotate.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 template "/usr/local/bin/render-lowzoom" do
   source "render-lowzoom.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 systemd_service "render-lowzoom" do
   description "Render low zoom tiles"
+  condition_path_exists_glob "!/run/update-lowzoom-*"
   user "tile"
   exec_start "/usr/local/bin/render-lowzoom"
   private_tmp true
@@ -553,10 +600,6 @@ service "render-lowzoom.timer" do
   action [:enable, :start]
 end
 
-file "/etc/cron.d/render-lowzoom" do
-  action :delete
-end
-
 package "liblockfile-simple-perl"
 package "libfilesys-df-perl"
 
@@ -564,19 +607,22 @@ template "/usr/local/bin/cleanup-tiles" do
   source "cleanup-tiles.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 tile_directories = node[:tile][:styles].collect do |_, style|
   style[:tile_directories].collect { |directory| directory[:name] }
 end.flatten.sort.uniq
 
-template "/etc/cron.d/cleanup-tiles" do
-  source "cleanup-tiles.cron.erb"
-  owner "root"
-  group "root"
-  mode 0o644
-  variables :directories => tile_directories
+tile_directories.each do |directory|
+  label = directory.gsub("/", "-")
+
+  cron_d "cleanup-tiles#{label}" do
+    minute "0"
+    user "www-data"
+    command "ionice -c 3 /usr/local/bin/cleanup-tiles #{directory}"
+    mailto "admins@openstreetmap.org"
+  end
 end
 
 munin_plugin "mod_tile_fresh"
@@ -591,3 +637,11 @@ munin_plugin "renderd_zoom"
 munin_plugin "renderd_zoom_time"
 
 munin_plugin "replication_delay"
+
+prometheus_exporter "modtile" do
+  port 9494
+end
+
+prometheus_exporter "renderd" do
+  port 9393
+end
index 8df11453b66850799e2ce63c65145801e709e894..e6f8ade1cbb135d3aa427acdb80e50b134183c06 100644 (file)
@@ -12,8 +12,8 @@
   #
   SSLEngine on
   SSLProxyEngine on
-  SSLCertificateFile /etc/ssl/certs/<%= node.name %>.pem
-  SSLCertificateKeyFile /etc/ssl/private/<%= node.name %>.key
+  SSLCertificateFile /etc/ssl/certs/<%= node[:fqdn] %>.pem
+  SSLCertificateKeyFile /etc/ssl/private/<%= node[:fqdn] %>.key
 
   # Configure location of static files and CGI scripts
   DocumentRoot /srv/tile.openstreetmap.org/html
@@ -25,6 +25,9 @@
 <% cache.ipaddresses(:role => :external).sort.each do |address| -%>
   RemoteIPTrustedProxy <%= address %>
 <% end -%>
+<% end -%>
+<% @fastly.sort.each do |address| -%>
+  RemoteIPTrustedProxy <%= address %>
 <% end -%>
 
   # Setup logging
@@ -40,6 +43,9 @@
   # Add diagnostics header to identify render server
   Header set X-TileRender "<%= node.name %>"
 
+  # Tell clients to use stale tiles if necessary
+  Header append Cache-Control "stale-while-revalidate=604800, stale-if-error=604800" "expr=%{CONTENT_TYPE} == 'image/png'"
+
   # Remove Proxy request header to mitigate https://httpoxy.org/
   RequestHeader unset Proxy early
 
@@ -52,9 +58,9 @@
   RewriteRule ^/(\d+)/(\d+)/(\d+)\.png/dirty/?$   /default/$1/$2/$3.png/dirty  [PT,T=text/plain,L]
 
   # Historical Files redirect
-  RedirectPermanent /processed_p.tar.bz2 https://planet.openstreetmap.org/historical-shapefiles/processed_p.tar.bz2
-  RedirectPermanent /shoreline_300.tar.bz2 https://planet.openstreetmap.org/historical-shapefiles/shoreline_300.tar.bz2
-  RedirectPermanent /world_boundaries-spherical.tgz https://planet.openstreetmap.org/historical-shapefiles/world_boundaries-spherical.tgz
+  RedirectPermanent /processed_p.tar.bz2 https://planet.openstreetmap.org/historical-shapefiles/
+  RedirectPermanent /shoreline_300.tar.bz2 https://planet.openstreetmap.org/historical-shapefiles/
+  RedirectPermanent /world_boundaries-spherical.tgz https://planet.openstreetmap.org/historical-shapefiles/
 
   # Redirect ACME certificate challenges
   RedirectPermanent /.well-known/acme-challenge/ http://acme.openstreetmap.org/.well-known/acme-challenge/
diff --git a/cookbooks/tile/templates/default/cleanup-tiles.cron.erb b/cookbooks/tile/templates/default/cleanup-tiles.cron.erb
deleted file mode 100644 (file)
index 28c631a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-
-MAILTO=admins@openstreetmap.org
-
-<% @directories.each do |directory| -%>
-0 * * * * www-data ionice -c 3 /usr/local/bin/cleanup-tiles <%= directory %>
-<% end -%>
index eb108e95e7d0c13f25034c02d1bc4c0c535a30e4..721660bb16795b234bf5779c91e76b099578f11d 100644 (file)
@@ -20,7 +20,7 @@ my $tempfile = tmpnam();
 
 if (df($tiledir)->{per} > 88)
 {
-    system("find", $tiledir, "-xdev", "-name", "lost+found", "-prune", "-o", "-type", "f", "-name", "*.meta", "-atime", "+3", "-fprintf", $tempfile, "%A@ %p\n");
+    system("find", $tiledir, "-xdev", "-name", "lost+found", "-prune", "-o", "-type", "f", "-name", "*.meta", "-atime", "+2", "-fprintf", $tempfile, "%A@ %p\n");
 
     open(TILES, "-|", "sort", "-n", $tempfile) || die "Can't open $tempfile: $!";
 
index 03af6549f4fec1510d24258b04e41c9034f795ff..e3e3852a0f4e91c573d59953b5c899d22c116366 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python -u
+#!/usr/bin/python3 -u
 # -*- coding: utf-8 -*-
 
 import cgi
@@ -22,35 +22,35 @@ resource.setrlimit(resource.RLIMIT_AS,(4000000000, 4000000000))
 
 # Routine to output HTTP headers
 def output_headers(content_type, filename = "", length = 0):
-  print "Cache-Control: no-cache, no-store, must-revalidate')"
-  print "Pragma: no-cache"
-  print "Expires: 0"
-  print "Content-Type: %s" % content_type
+  print("Cache-Control: no-cache, no-store, must-revalidate')")
+  print("Pragma: no-cache")
+  print("Expires: 0")
+  print("Content-Type: %s" % content_type)
   if filename:
-    print "Content-Disposition: attachment; filename=\"%s\"" % filename
+    print("Content-Disposition: attachment; filename=\"%s\"" % filename)
   if length:
-    print "Content-Length: %d" % length
-  print ""
+    print("Content-Length: %d" % length)
+  print("")
 
 # Routine to report an error
 def output_error(message):
   output_headers("text/html")
-  print "<html>"
-  print "<head>"
-  print "<title>Error</title>"
-  print "</head>"
-  print "<body>"
-  print "<h1>Error</h1>"
-  print "<p>%s</p>" % message
-  print "</body>"
-  print "</html>"
+  print("<html>")
+  print("<head>")
+  print("<title>Error</title>")
+  print("</head>")
+  print("<body>")
+  print("<h1>Error</h1>")
+  print("<p>%s</p>" % message)
+  print("</body>")
+  print("</html>")
 
 # Make sure we have a user agent
-if not os.environ.has_key('HTTP_USER_AGENT'):
+if 'HTTP_USER_AGENT' not in os.environ:
   os.environ['HTTP_USER_AGENT'] = 'NONE'
 
 # Get the cache server name
-if os.environ.has_key('HTTP_VIA'):
+if 'HTTP_VIA' in os.environ:
   cache_server = re.search('[a-z0-9-]+\.openstreetmap\.org', os.environ['HTTP_VIA']).group(0)
 else:
   cache_server = None
@@ -59,35 +59,35 @@ else:
 loadavg = float(open("/proc/loadavg").readline().split(" ")[0])
 
 output_headers("text/html")
-print "<html>"
-print "<head>"
-print "<title>tile.openstreetmap.org debug</title>"
-print "</head>"
-print "<body>"
-print "<h1>tile.openstreetmap.org debug</h1>"
-print "<h2>Server Stats</h2>"
+print("<html>")
+print("<head>")
+print("<title>tile.openstreetmap.org debug</title>")
+print("</head>")
+print("<body>")
+print("<h1>tile.openstreetmap.org debug</h1>")
+print("<h2>Server Stats</h2>")
 if cache_server:
-  print "<p><b>Cache Server</b>: %s</p>" % cache_server
-print "<p>"
-print "<b>Render Server</b>: <%= node['fqdn'] %><br />"
-print "<b>Load Average</b>: %s</p>" % loadavg
-print "<h2>File Status</h2>"
-print "<p>"
+  print("<p><b>Cache Server</b>: %s</p>" % cache_server)
+print("<p>")
+print("<b>Render Server</b>: <%= node['fqdn'] %><br />")
+print("<b>Load Average</b>: %s</p>" % loadavg)
+print("<h2>File Status</h2>")
+print("<p>")
 <%
 node[:tile][:data].each do |name,data|
   url = data[:url]
   file = "/srv/tile.openstreetmap.org/data/#{File.basename(url)}"
   file_basename = File.basename(url)
 -%>
-print "<b>%s</b> last modified: %s<br />" % ("<%= file_basename %>", time.ctime(os.path.getmtime("<%= file %>")))
+print("<b>%s</b> last modified: %s<br />" % ("<%= file_basename %>", time.ctime(os.path.getmtime("<%= file %>"))))
 <%
 end
 -%>
-print "</p>"
-print "<h2>Browser Request Headers</h2>"
-print "<p>"
-for param in os.environ.keys():
-  print "<b>%20s</b>: %s<br />" % (param, os.environ[param])
-print "</p>"
-print "</body>"
-print "</html>"
+print("</p>")
+print("<h2>Browser Request Headers</h2>")
+print("<p>")
+for param in sorted(os.environ):
+  print("<b>%20s</b>: %s<br />" % (param, os.environ[param]))
+print("</p>")
+print("</body>")
+print("</html>")
index 2f6a97d773ee9ddb27ab442477327f0ab04bcca9..3a023d6b2bb71ee85d372997ab1f39522f92a2f9 100644 (file)
@@ -10,6 +10,6 @@ args = [
   "--max", "<%= node[:tile][:styles].collect { |n,d| d[:max_zoom] }.max %>"
 ]
 
-Dir.glob("/var/lib/replicate/expire-queue/changes-*.gz").each do |f|
+Dir.glob("/var/lib/replicate/expire-queue/changes-*.gz").sort.each do |f|
    system("/usr/local/bin/expire-tiles-single", *args, f) && File::unlink(f)
 end
index 0cd115271c5bcf313560dd6fff074b2e7f95be42..b8075a17a93e7d9b7eacd0c1fb1e17c897f12489 100644 (file)
@@ -1,9 +1,9 @@
-#!/usr/bin/python -u
+#!/usr/bin/python3 -u
 # -*- coding: utf-8 -*-
 
 import cairo
 import cgi
-import Cookie
+import http.cookies
 import mapnik
 import os
 import pyotp
@@ -23,17 +23,17 @@ resource.setrlimit(resource.RLIMIT_AS,(4000000000, 4000000000))
 
 # Routine to output HTTP headers
 def output_headers(content_type, filename = "", length = 0):
-  print "Content-Type: %s" % content_type
+  print("Content-Type: %s" % content_type)
   if filename:
-    print "Content-Disposition: attachment; filename=\"%s\"" % filename
+    print("Content-Disposition: attachment; filename=\"%s\"" % filename)
   if length:
-    print "Content-Length: %d" % length
-  print ""
+    print("Content-Length: %d" % length)
+  print("")
 
 # Routine to output the contents of a file
 def output_file(file):
   file.seek(0)
-  shutil.copyfileobj(file, sys.stdout)
+  shutil.copyfileobj(file, sys.stdout.buffer)
 
 # Routine to get the size of a file
 def file_size(file):
@@ -41,17 +41,17 @@ def file_size(file):
 
 # Routine to report an error
 def output_error(message, status = "400 Bad Request"):
-  print "Status: %s" % status
+  print("Status: %s" % status)
   output_headers("text/html")
-  print "<html>"
-  print "<head>"
-  print "<title>Error</title>"
-  print "</head>"
-  print "<body>"
-  print "<h1>Error</h1>"
-  print "<p>%s</p>" % message
-  print "</body>"
-  print "</html>"
+  print("<html>")
+  print("<head>")
+  print("<title>Error</title>")
+  print("</head>")
+  print("<body>")
+  print("<h1>Error</h1>")
+  print("<p>%s</p>" % message)
+  print("</body>")
+  print("</html>")
 
 # Create TOTP token validator
 totp = pyotp.TOTP('<%= @totp_key %>', interval = 3600)
@@ -60,18 +60,18 @@ totp = pyotp.TOTP('<%= @totp_key %>', interval = 3600)
 form = cgi.FieldStorage()
 
 # Import cookies
-cookies = Cookie.SimpleCookie(os.environ.get('HTTP_COOKIE'))
+cookies = http.cookies.SimpleCookie(os.environ.get('HTTP_COOKIE'))
 
 # Make sure we have a user agent
-if not os.environ.has_key('HTTP_USER_AGENT'):
+if 'HTTP_USER_AGENT' not in os.environ:
   os.environ['HTTP_USER_AGENT'] = 'NONE'
 
 # Make sure we have a referer
-if not os.environ.has_key('HTTP_REFERER'):
+if 'HTTP_REFERER' not in os.environ:
   os.environ['HTTP_REFERER'] = 'NONE'
 
 # Look for TOTP token
-if cookies.has_key('_osm_totp_token'):
+if '_osm_totp_token' in cookies:
   token = cookies['_osm_totp_token'].value
 else:
   token = None
@@ -97,13 +97,13 @@ elif os.environ['HTTP_REFERER'] == '<%= referer %>':
   # Block scraper
   output_error("The server is too busy at the moment. Please wait a few minutes before trying again.", "503 Service Unavailable")
 <% end -%>
-elif not form.has_key("bbox"):
+elif "bbox" not in form:
   # No bounding box specified
   output_error("No bounding box specified")
-elif not form.has_key("scale"):
+elif "scale" not in form:
   # No scale specified
   output_error("No scale specified")
-elif not form.has_key("format"):
+elif "format" not in form:
   # No format specified
   output_error("No format specified")
 else:
@@ -152,13 +152,13 @@ else:
           mapnik.render(map, image)
           png = image.tostring("png")
           output_headers("image/png", "map.png", len(png))
-          sys.stdout.write(png)
+          sys.stdout.buffer.write(png)
         elif form.getvalue("format") == "jpeg":
           image = mapnik.Image(map.width, map.height)
           mapnik.render(map, image)
           jpeg = image.tostring("jpeg")
           output_headers("image/jpeg", "map.jpg", len(jpeg))
-          sys.stdout.write(jpeg)
+          sys.stdout.buffer.write(jpeg)
         elif form.getvalue("format") == "svg":
           file = tempfile.NamedTemporaryFile(prefix = "export")
           surface = cairo.SVGSurface(file.name, map.width, map.height)
index 55a98a754557af9e2478e0e1c952b6ed4b9f47cb..95e4ed6e8f943610752b21d2e67cb02f96ef0efe 100644 (file)
@@ -16,9 +16,9 @@ function update_<%= style %>
     --timestamp=${timestamp} \
     --tile-dir=/srv/tile.openstreetmap.org/tiles \
     --socket=/var/run/renderd/renderd.sock \
-    --num-threads=<%= node[:cpu][:total] - 2 %> \
+    --num-threads=<%= node[:cpu][:total] - 1 %> \
     --map="<%= style %>" \
-    --max-load=70 \
+    --max-load=<%= node[:cpu][:total] %> \
     --min-zoom=0 --max-zoom=12
 }
 
index 69479e0b013556ace35eb3079f6d1859a5edf9e1..d02202d066d0ab656989a0c698df5d1ce090c994 100644 (file)
@@ -2,7 +2,7 @@
 
 [renderd]
 socketname=/var/run/renderd/renderd.sock
-num_threads=<%= node[:cpu][:total] - 2 %>
+num_threads=<%= node[:cpu][:total] - 1 %>
 tile_dir=/srv/tile.openstreetmap.org/tiles
 stats_file=/var/run/renderd/renderd.stats
 
index 81fc66419e153fa5e4e7970bae7b816ff02c3553..4e96d767d8dd1696d44c4a78427b3c2c68e9e170 100644 (file)
@@ -17,6 +17,11 @@ exec > /var/log/tile/replicate.log 2>&1
 
 # Change to the replication state directory
 cd /var/lib/replicate
+<% if @postgresql_version >= 12 -%>
+
+# Disable JIT and parallel workers in postgres
+export PGOPTIONS="-c jit=off -c max_parallel_workers_per_gather=0"
+<% end -%>
 
 # Install exit handler
 trap onexit EXIT
@@ -31,7 +36,7 @@ do
     cp sequence.txt sequence-prev.txt
 
     # Fetch the next set of changes
-    pyosmium-get-changes --sequence-file=sequence.txt --outfile=${file}
+    pyosmium-get-changes --server=<%= node[:tile][:replication][:url] %> --sequence-file=sequence.txt --outfile=${file}
 
     # Save exit status
     status=$?
@@ -47,13 +52,20 @@ do
 
         # Apply the changes to the database
         osm2pgsql --database gis --slim --append --number-processes=1 \
-<% if node[:tile][:node_file] -%>
-                  --flat-nodes=<%= node[:tile][:node_file] %> \
+<% if node[:tile][:database][:node_file] -%>
+                  --flat-nodes=<%= node[:tile][:database][:node_file] %> \
+<% end -%>
+<% if node[:tile][:database][:multi_geometry] -%>
+                  --multi-geometry \
+<% end -%>
+<% if node[:tile][:database][:hstore] -%>
+                  --hstore \
+<% end -%>
+<% if node[:tile][:database][:style_file] -%>
+                  --style=<%= node[:tile][:database][:style_file] %> \
 <% end -%>
-<% if node[:tile][:styles][:default][:revision] >= "v4.0.0" -%>
-                  --multi-geometry --hstore \
-                  --style=/srv/tile.openstreetmap.org/styles/default/openstreetmap-carto.style \
-                  --tag-transform-script=/srv/tile.openstreetmap.org/styles/default/openstreetmap-carto.lua \
+<% if node[:tile][:database][:tag_transform_script] -%>
+                  --tag-transform-script=<%= node[:tile][:database][:tag_transform_script] %> \
 <% end -%>
                   ${file}
 
index 277c71fc6f7f2d7c062739c614b6c0ec02b7e733..85f32c13d3688527f20383b3180b7eceb376568c 100644 (file)
@@ -12,9 +12,9 @@ function update_tiles
     --timestamp=$(stat -c %Y "/srv/tile.openstreetmap.org/styles/<%= @style %>/project.xml") \
     --tile-dir=/srv/tile.openstreetmap.org/tiles \
     --socket=/var/run/renderd/renderd.sock \
-    --num-threads=<%= node[:cpu][:total] - 2 %> \
+    --num-threads=<%= node[:cpu][:total] - 1 %> \
     --map="<%= @style %>" \
-    --max-load=70 \
+    --max-load=<%= node[:cpu][:total] %> \
     --min-zoom=0 --max-zoom=12
 }
 
index a552ee6fc2a22e7f52703c5db00cf16b3884d9e2..a830e0b38db4b95a58e3517cbc2cffd8f6014602 100644 (file)
@@ -1,5 +1,4 @@
 default[:tilecache][:tile_parent] = "render.openstreetmap.org"
-default[:tilecache][:tile_siblings] = []
 
 # Per IP bucket refill rate
 default[:tilecache][:ip_bucket_refill] = 4096
@@ -9,3 +8,6 @@ default[:tilecache][:ip_bucket_size] = 67108864
 default[:tilecache][:net_bucket_refill] = 8192
 # Per Class C bucket size
 default[:tilecache][:net_bucket_size] = 134217728
+
+# Enable nginx cache
+default[:nginx][:cache][:proxy][:enable] = true
diff --git a/cookbooks/tilecache/files/default/tilecache-curl-time.txt b/cookbooks/tilecache/files/default/tilecache-curl-time.txt
new file mode 100644 (file)
index 0000000..3da02a7
--- /dev/null
@@ -0,0 +1 @@
+%{time_total},%{http_code},%{url_effective},%{time_namelookup},%{time_connect},%{time_appconnect},%{time_pretransfer},%{time_redirect},%{time_starttransfer}\n
index a2074862414cd9f79d50f1bd680f2ca0af7ca3fa..38abbe7e2825cc988d18ba09a7e045ef841437c8 100644 (file)
@@ -6,8 +6,9 @@ description       "Installs and configures a tile cache"
 
 version           "1.0.0"
 supports          "ubuntu"
-depends           "ssl"
-depends           "squid"
-depends           "nginx"
-depends           "munin"
 depends           "fail2ban"
+depends           "munin"
+depends           "nginx"
+depends           "ohai"
+depends           "squid"
+depends           "ssl"
index 4afda5568d3b0b1d3bbea6ac9b0071bd75d5d4a9..d3f1dccfaa657786bc3d7776e53920e8c4473544 100644 (file)
 
 require "ipaddr"
 
-include_recipe "ssl"
-include_recipe "squid"
-include_recipe "nginx"
 include_recipe "fail2ban"
+include_recipe "munin"
+include_recipe "nginx"
+include_recipe "squid"
+include_recipe "ssl"
 
 package "apache2" do
   action :remove
 end
 
 package %w[
+  curl
   xz-utils
   openssl
 ]
@@ -52,6 +54,7 @@ tilecaches.each do |cache|
       dest_ports "3128"
       source_ports "1024:"
     end
+
     firewall_rule "accept-squid-icp" do
       action :accept
       family "inet"
@@ -61,6 +64,7 @@ tilecaches.each do |cache|
       dest_ports "3130"
       source_ports "3130"
     end
+
     firewall_rule "accept-squid-icp-reply" do
       action :accept
       family "inet"
@@ -70,6 +74,26 @@ tilecaches.each do |cache|
       dest_ports "3130"
       source_ports "3130"
     end
+
+    firewall_rule "accept-squid-htcp" do
+      action :accept
+      family "inet"
+      source "net:#{address}"
+      dest "fw"
+      proto "udp"
+      dest_ports "4827"
+      source_ports "4827"
+    end
+
+    firewall_rule "accept-squid-htcp-reply" do
+      action :accept
+      family "inet"
+      source "fw"
+      dest "net:#{address}"
+      proto "udp"
+      dest_ports "4827"
+      source_ports "4827"
+    end
   end
 end
 
@@ -84,7 +108,7 @@ template "/etc/logrotate.d/squid" do
   source "logrotate.squid.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 nginx_site "default" do
@@ -95,15 +119,30 @@ template "/usr/local/bin/nginx_generate_tilecache_qos_map" do
   source "nginx_generate_tilecache_qos_map.erb"
   owner "root"
   group "root"
-  mode 0o750
+  mode "750"
   variables :totp_key => web_passwords["totp_key"]
 end
 
-template "/etc/cron.d/tilecache" do
-  source "cron.erb"
-  owner "root"
-  group "root"
-  mode 0o644
+cron_d "tilecache" do
+  action :delete
+end
+
+cron_d "tilecache-generate-qos-map" do
+  minute "0"
+  user "root"
+  command "/usr/local/bin/nginx_generate_tilecache_qos_map"
+end
+
+cron_d "tilecache-curl-time" do
+  user "www-data"
+  command "/srv/tilecache/tilecache-curl-time"
+end
+
+cron_d "tilecache-curl-time-cleanup" do
+  minute "15"
+  hour "0"
+  user "www-data"
+  command "/srv/tilecache/tilecache-curl-time-cleanup"
 end
 
 execute "execute_nginx_generate_tilecache_qos_map" do
@@ -133,7 +172,7 @@ template "/etc/logrotate.d/nginx" do
   source "logrotate.nginx.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 fail2ban_jail "squid" do
@@ -147,3 +186,41 @@ tilerenders.each do |render|
     conf_variables :host => render[:fqdn]
   end
 end
+
+directory "/srv/tilecache" do
+  owner "root"
+  group "root"
+  mode "755"
+end
+
+directory "/srv/tilecache/data" do
+  owner "www-data"
+  group "www-data"
+  mode "755"
+end
+
+cookbook_file "/srv/tilecache/tilecache-curl-time.txt" do
+  source "tilecache-curl-time.txt"
+  owner "root"
+  group "root"
+  mode "755"
+end
+
+template "/srv/tilecache/tilecache-curl-time" do
+  source "tilecache-curl-time.erb"
+  owner "root"
+  group "root"
+  mode "755"
+  variables :caches => tilecaches, :renders => tilerenders
+end
+
+template "/srv/tilecache/tilecache-curl-time-cleanup" do
+  source "tilecache-curl-time-cleanup.erb"
+  owner "root"
+  group "root"
+  mode "755"
+end
+
+ohai_plugin "tilecache" do
+  template "ohai.rb.erb"
+end
diff --git a/cookbooks/tilecache/templates/default/cron.erb b/cookbooks/tilecache/templates/default/cron.erb
deleted file mode 100644 (file)
index 32fb067..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-
-0 * * * * root /usr/local/bin/nginx_generate_tilecache_qos_map
index 0c45dcab0b13a5a8c2763ad1b0c0705c52b5ba3a..40a2240b419c66c6bb5984a24373fb7ed689bb88 100644 (file)
@@ -4,6 +4,7 @@
   daily
   compress
   compresscmd /usr/bin/xz
+  compressoptions --threads=<%= [ node[:cpu][:total] / 2, 1 ].max.ceil %>
   uncompresscmd /usr/bin/unxz
   compressext .xz
   rotate 2
   nocreate
   sharedscripts
   postrotate
+<% if node[:lsb][:release].to_f < 20.04 -%>
     test ! -e /var/run/squid.pid || /usr/sbin/squid -k rotate
+<% else -%>
+    test ! -e /run/squid/squid.pid || /usr/sbin/squid -k rotate
+<% end -%>
   endscript
   lastaction
     /usr/bin/rsync --preallocate /var/log/squid/access.log.1.xz ironbelly::logs/tile.openstreetmap.org/<%= node[:hostname] %>-`date -d "-1 days" +%Y-%m-%d`.xz || true
index 869b30de63de5d7f35a0223af28321c93b80021a..deec588c375f672b5303e580c73e38c85627671d 100755 (executable)
@@ -47,4 +47,4 @@ default '_osm_totp_token=${QOS_TOKEN_DEFAULT}; Max-Age=${VALID_TOKEN}; Domain=op
 EOF
 
 # Check config, reload config and fail safe
-/etc/init.d/nginx configtest 2>/dev/null && /bin/systemctl try-reload-or-restart nginx
+/etc/init.d/nginx configtest 2>/dev/null && /bin/systemctl try-reload-or-restart nginx
index c3b220f2da7e070d9ef088ae357a1f9b009d9c24..338e0d51d01889acfaf2f9877e9772c53a359de5 100644 (file)
@@ -1,43 +1,47 @@
 # DO NOT EDIT - This file is being maintained by Chef
 
 upstream tile_cache_backend {
-  server 127.0.0.1;
+  server 127.0.0.1:8080 weight=1000 max_fails=32;
+  server 127.0.0.2:8080 weight=1000 max_fails=32;
 
-  # Add the other caches to relieve pressure if local squid failing
+  # Add the tile_siblings caches to relieve pressure if local squid failing
   # Balancer: round-robin
+<% server_weight = 1000 -%>
+<% Array(@node[:tilecache][:tile_siblings]).each do |cache_peer| -%>
 <% @caches.each do |cache| -%>
+<% if cache_peer == cache[:fqdn] -%>
 <% if cache[:hostname] != node[:hostname] -%>
-<% if node[:tilecache][:tile_siblings].include? cache[:fqdn] -%>
 <% cache.ipaddresses(:family => :inet, :role => :external).sort.each do |address| -%>
-  server <%= address %> backup; # Server <%= cache[:hostname] %>
+  server <%= address %>:80 weight=<%= server_weight %> max_fails=32 backup; # Server <%= cache[:hostname] %>
+<% server_weight -= server_weight.div(2) -%>
+<% end -%>
 <% end -%>
 <% end -%>
 <% end -%>
 <% end -%>
 
-  keepalive 1024;
-  keepalive_requests 1024;
+  keepalive 128;
 }
 
 # Geo Map of tile caches
 geo $tile_cache {
-  default 0;
+  default "client";
 <% @caches.each do |cache| -%>
 <% cache.ipaddresses(:family => :inet, :role => :external).sort.each do |address| -%>
-  <%= address %> 1; # <%= cache[:hostname] %>
+  <%= address %> "cache"; # <%= cache[:hostname] %>
 <% end -%>
 <% end -%>
 }
 
 # Rates table based on current cookie value
-map $cookie__osm_totp_token $limit_rate_qos {
-  include /etc/nginx/conf.d/tile_qos_rates.map;
-}
+map $cookie__osm_totp_token $limit_rate_qos {
+#  include /etc/nginx/conf.d/tile_qos_rates.map;
+}
 
 # Set-Cookie table based on current cookie value
-map $cookie__osm_totp_token $cookie_qos_token_set {
-  include /etc/nginx/conf.d/tile_qos_cookies.map;
-}
+map $cookie__osm_totp_token $cookie_qos_token_set {
+#  include /etc/nginx/conf.d/tile_qos_cookies.map;
+}
 
 map $http_user_agent $approved_scraper {
   default                   0; # Not approved
@@ -48,48 +52,163 @@ map $http_user_agent $approved_scraper {
 map $http_user_agent $denied_scraper {
   default                0; # Not denied
   ''                     1; # No User-Agent Set
-  '~^Python\-urllib\/'   1; # Library Default
-  '~^python\-requests\/' 1; # Library Default
-  '~^node\-fetch\/'      1; # Library Default
-  '~^R$'                 1; # Library Default
-  '~^Java\/'             1; # Library Default
-  '~^tiles$'             1; # Library Default
-  '~^runtastic'          1; # App
-  'Mozilla/4.0'          1; # Fake
-  'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)' 1;  # Fake
+  '-'                    1;
+
+  # Library defaults
+  '~^Python\-urllib\/'   1;
+  '~^python\-requests\/' 1;
+  '~^node\-fetch\/'      1;
+  '~^R$'                 1;
+  '~^Java\/'             1;
+  '~^tiles$'             1;
+  '~^okhttp\/'           1;
+  '~^Microsoft-ATL-Native\/' 1;
+  '/n software IPWorks HTTP/S Component - www.nsoftware.com' 1;
+  '~^Wget\/'             1;
+  'java'                 1;
+
+  # Library defaults or fakes
+  'Android'              1;
+  'kc_android'           1;
+  'host'                 1;
+  '~^maptestapp'         1;
+  'Other'                1;
+  'osmdroid'             1;
+  '~^tilelive-http'      1;
+  '~^Java-http-client'   1;
+
+  # Fakes
+  'Mozilla/4.0'          1;
+  'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)' 1;
+
+  # Bulk downloaders
+  'C# TilesDownloader'   1;
+  'MapDownloader'        1;
+  '~^staticmaps'         1;
+
+  # Overusage apps
+  '~^runtastic'          1;
+  '~^Where\ my\ children' 1;
+  'nossoonibusjp.android.crosswalk' 1;
+  'br.com.concisoti.potybus' 1;
+  'com.soft373.taptaxi'  1;
+  'com.kradac.ktxcore'   1;
+  '~^ru.crowdsystems.topcontrol.knd' 1;
+  'pl.itaxi.driver'      1;
+  'net.uztaxi.driver'    1;
+  'OSMDroid/2.1 (its; rutaxi 3.28.0)' 1;
+  'com.helleniccomms.mercedes.driver' 1;
+  'ru.taximaster.www'    1;
+  'com.arobs.trackgps'   1;
+  'com.helleniccomms.asteras.driver' 1;
+
+  # Malware
+  'Agent Smith'          1;
+  # '~[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}' 1; # Fake UA
 }
 
 map $http_referer $denied_referer {
   default                          0; # Not denied
-  'http://www.openstreetmap.org/'  1; # Faked
-  'http://www.openstreetmap.org'   1; # Faked
-  'http://openstreetmap.org/'      1; # Faked
-  'http://openstreetmap.org'       1; # Faked
-  'http://www.osm.org/'            1; # Faked
-  'http://www.osm.org'             1; # Faked
-  'http://osm.org/'                1; # Faked
-  'http://osm.org'                 1; # Faked
+  # Faked sites
+  'http://www.openstreetmap.org/'  1;
+  'http://www.openstreetmap.org'   1;
+  'https://www.openstreetmap.org'  1;
+  'http://openstreetmap.org/'      1;
+  'http://openstreetmap.org'       1;
+  'https://openstreetmap.org'      1;
+  'http://www.osm.org/'            1;
+  'http://www.osm.org'             1;
+  'http://osm.org/'                1;
+  'http://osm.org'                 1;
+  'http://google.com'              1;
+  'http://www.google.com'          1;
+  'http://google.com/'             1;
+  'http://www.google.com/'         1;
+  'https://google.com'             1;
+  'https://www.google.com'         1;
+  'https://google.com/'            1;
+  'https://www.google.com/'        1;
+  'http://www.microsoft.com/'      1;
+
+  # Overusing websites
+  '~^https?://pmap\.kuku\.lu/'           1;
+  '~^https?://[^.]*\.pmap\.kuku\.lu/'    1;
+  '~^https?://fastpokemap\.com/'         1;
+  '~^https?://[^.]*\.fastpokemap\.com/'  1;
+  '~^https?://pkget\.com/'               1;
+  '~^https?://[^.]*\.pkget\.com/'        1;
+  '~^https?://twpkinfo\.com/'            1;
+  '~^https?://[^.]*\.twpkinfo\.com/'     1;
+  '~^https?://9db\.jp/'                  1;
+  '~^https?://[^.]*\.9db\.jp/'           1;
+  '~^https?://clustrmaps\.com/'          1;
+  '~^https?://[^.]*\.clustrmaps\.com/'   1;
+  '~^https?://geoportal360\.pl/'         1;
+  '~^https?://skelbiu\.lt/'              1;
+  '~^https?://[^.]*\.skelbiu\.lt/'       1;
+  '~^https?://wialon\.[^.]*/'            1; # wialon has many domains, so block them all
+  '~^https?://[^.]*\.wialon\.[^.]*/'     1;
+  '~^https?://gps-trace\.com/'           1;
+  '~^https?://[^.]*\.gps-trace\.com/'    1;
+  '~^https?://cellmapper\.net/'          1;
+  '~^https?://[^.]*\.cellmapper\.net/'   1;
+}
+
+map $http_referer $censored_referer {
+  default                                 0; # Not denied
+  # Blocked on board instructions
+  '~^https?://schiebt-sie-ab\.de/'        1;
+  '~^https?://[^.]*\.schiebt-sie-ab\.de/' 1;
+}
+
+
+map $http_referer $osm_referer {
+  default                                 '';    # False
+  '~^https:\/\/www\.openstreetmap\.org\/' 'osm'; # True
 }
 
 # Limit Cache-Control header to only approved User-Agents
-map $http_user_agent $limit_http_cache_control {
-  default '';                              # Unset Header
-  '~^Mozilla\/5\.0\ QGIS\/' '';            # Unset Header
-  '~^Mozilla\/5\.0\ ' $http_cache_control; # Pass Header
+map $tile_cache$osm_referer$http_user_agent $limit_http_cache_control {
+  default '';                             # Unset Header
+  '~^clientosmMozilla\/5\.0\ \(X11'       $http_cache_control; # Pass Header
+  '~^clientosmMozilla\/5\.0\ \(Windows'   $http_cache_control; # Pass Header
+  '~^clientosmMozilla\/5\.0\ \(iPhone'    $http_cache_control; # Pass Header
+  '~^clientosmMozilla\/5\.0\ \(Macintosh' $http_cache_control; # Pass Header
+  '~^clientosmMozilla\/5\.0\ \(Linux'     $http_cache_control; # Pass Header
 }
 
 # Limit Pragma header to only approved User-Agents
-map $http_user_agent $limit_http_pragma {
-  default '';                       # Unset Header
-  '~^Mozilla\/5\.0\ QGIS\/' '';     # Unset Header
-  '~^Mozilla\/5\.0\ ' $http_pragma; # Pass Header
+map $tile_cache$osm_referer$http_user_agent $limit_http_pragma {
+  default '';                             # Unset Header
+  '~^clientosmMozilla\/5\.0\ \(X11'       $http_pragma; # Pass Header
+  '~^clientosmMozilla\/5\.0\ \(Windows'   $http_pragma; # Pass Header
+  '~^clientosmMozilla\/5\.0\ \(iPhone'    $http_pragma; # Pass Header
+  '~^clientosmMozilla\/5\.0\ \(Macintosh' $http_pragma; # Pass Header
+  '~^clientosmMozilla\/5\.0\ \(Linux'     $http_pragma; # Pass Header
+}
+
+# Find Browser User-Agents which are not sending a referer.
+# Browsers with no referer could be due to Browser extension or website Referrer-Policy
+map $tile_cache$http_referer$scheme$http_user_agent $deny_missing_referer {
+  default                                   0; # Not denied
+  '~^clienthttpsMozilla\/5\.0\ \(X11'       1;
+  '~^clienthttpsMozilla\/5\.0\ \(Windows'   1;
+  '~^clienthttpsMozilla\/5\.0\ \(iPhone'    1;
+  '~^clienthttpsMozilla\/5\.0\ \(Macintosh' 1;
+  '~^clienthttpsMozilla\/5\.0\ \(Linux'     1;
 }
 
 server {
-    listen       443 ssl deferred backlog=16384 reuseport fastopen=2048 http2 default_server;
+    # IPv4
+    listen       80 deferred backlog=16384 reuseport default_server;
+    listen       443 ssl deferred backlog=16384 reuseport http2 default_server;
+    # IPv6
+    listen       [::]:80 deferred backlog=16384 reuseport default_server;
+    listen       [::]:443 ssl deferred backlog=16384 reuseport http2 default_server;
     server_name  localhost;
 
     proxy_buffers 8 64k;
+    proxy_busy_buffers_size 64k;
 
     ssl_certificate      /etc/ssl/certs/tile.openstreetmap.org.pem;
     ssl_certificate_key  /etc/ssl/private/tile.openstreetmap.org.key;
@@ -101,90 +220,174 @@ server {
     # Immediately 404 layers we do not support
 <% for i in 20..99 do %>
     location /<%= i %>/ {
-      set $limit_rate 512;
       return 404;
     }
 <% end %>
 
     # Immediately 404 silly tile requests
+    location = /0/-1/-1.png {
+      return 404;
+    }
+    location = /0/-1/0.png {
+      return 404;
+    }
+    location = /0/-1/1.png {
+      return 404;
+    }
     location = /0/0/-1.png {
-      set $limit_rate 512;
       return 404;
     }
-    location = /1/0/-1.png {
-      set $limit_rate 512;
+    location = /0/0/1.png {
       return 404;
     }
-    location = /1/-1/0.png {
-      set $limit_rate 512;
+    location = /0/0/2.png {
       return 404;
     }
-    location = /1/-1/1.png {
-      set $limit_rate 512;
+    location = /0/1/-1.png {
+      return 404;
+    }
+    location = /0/1/0.png {
+      return 404;
+    }
+    location = /0/1/1.png {
+      return 404;
+    }
+    location = /0/1/2.png {
+      return 404;
+    }
+    location = /0/2/0.png {
+      return 404;
+    }
+    location = /0/2/1.png {
+      return 404;
+    }
+    location = /0/2/2.png {
       return 404;
     }
     location = /1/-1/-1.png {
-      set $limit_rate 512;
+      return 404;
+    }
+    location = /1/-1/0.png {
+      return 404;
+    }
+    location = /1/-1/1.png {
       return 404;
     }
     location = /1/-1/2.png {
-      set $limit_rate 512;
       return 404;
     }
-    location = /1/1/-1.png {
-      set $limit_rate 512;
+    location = /1/0/-1.png {
       return 404;
     }
-    location = /1/2/-1.png {
-      set $limit_rate 512;
+    location = /1/1/-1.png {
       return 404;
     }
-    location = /2/0/-1.png {
-      set $limit_rate 512;
+    location = /1/2/-1.png {
       return 404;
     }
     location = /2/-1/0.png {
-      set $limit_rate 512;
       return 404;
     }
     location = /2/-1/1.png {
-      set $limit_rate 512;
+      return 404;
+    }
+    location = /2/-1/2.png {
+      return 404;
+    }
+    location = /2/-1/3.png {
+      return 404;
+    }
+    location = /2/0/-1.png {
       return 404;
     }
     location = /2/1/-1.png {
-      set $limit_rate 512;
       return 404;
     }
-    location = /2/-1/2.png {
-      set $limit_rate 512;
+    location = /2/1/4.png {
       return 404;
     }
-    location = /2/-1/3.png {
-      set $limit_rate 512;
+    location = /2/2/4.png {
+      return 404;
+    }
+    location = /2/3/4.png {
+      return 404;
+    }
+    location = /2/4/0.png {
+      return 404;
+    }
+    location = /2/4/1.png {
+      return 404;
+    }
+    location = /2/4/2.png {
+      return 404;
+    }
+    location = /2/4/3.png {
+      return 404;
+    }
+    location = /2/4/4.png {
       return 404;
     }
 
+<% for i in 0..16 do %>
+<% if i == 0 -%>
+    # Default Fallback Location Handler (lowest)
     location / {
+<% elsif -%>
+    # Dedicated zoom handler for caching
+    location /<%= i %>/ {
+<% end %>
+      # Only allow GET / HEAD / OPTIONS (CORS) requests
+      limit_except GET HEAD OPTIONS {
+        deny all;
+      }
+
       proxy_pass http://tile_cache_backend;
       proxy_set_header X-Forwarded-For $remote_addr;
       proxy_http_version 1.1;
       proxy_set_header Connection '';
 
-      proxy_connect_timeout 5s;
+      proxy_connect_timeout 20s;
 
-      # Preserve host header.
-      proxy_set_header Host $host;
-      # Do not pass cookies to backends.
-      proxy_set_header Cookie '';
-      # Do not pass Accept-Encoding to backends.
-      proxy_set_header Accept-Encoding '';
+      proxy_next_upstream_tries 2;
+
+      # Replace host header.
+      proxy_set_header Host 'tile.openstreetmap.org';
+      # Drop all request headers and request body
+      proxy_pass_request_headers off;
+      proxy_pass_request_body off;
 
       # Do not allow setting cookies from backends due to caching.
       proxy_ignore_headers Set-Cookie;
       proxy_hide_header Set-Cookie;
 
+<% if i != 0 -%>
+      # Caching
+      proxy_cache "proxy_cache_zone";
+      proxy_cache_lock on;
+      proxy_cache_valid 200 2d;
+      proxy_cache_valid 404 15m;
+      # Serve stale cache on errors or if updating
+      proxy_cache_use_stale error timeout updating http_404 http_500 http_503 http_504;
+      # If in cache as stale, serve stale and update in background
+      proxy_cache_background_update on;
+      # Workaround nginx async bug which causes stale cache replies to wait for the async backend cache update reply (seen in v1.16.0)
+      keepalive_requests 0;
+      # Enable revalidation using If-Modified-Since and If-None-Match for stale items
+      proxy_cache_revalidate on;
+      proxy_cache_min_uses 4;
+
+      add_header x-cache-status "$upstream_cache_status - <%= node[:hostname] %>";
+<% else %>
+      # Severely rate limit Browser UAs which are not sending a referer.
+      # With no referer we do not know who is using tiles
+      if ($deny_missing_referer) {
+        set $limit_rate 1024;
+        add_header x-cache-ratelimit "missing-referer";
+      }
+<% end -%>
+
       # Set a QoS cookie if none presented (uses nginx Map)
-      add_header Set-Cookie $cookie_qos_token_set;
+      add_header Set-Cookie $cookie_qos_token_set;
 <% if node[:ssl][:strict_transport_security] -%>
       # Ensure Strict-Transport-Security header is removed from proxied server responses
       proxy_hide_header Strict-Transport-Security;
@@ -194,12 +397,12 @@ server {
 <% end -%>
 
       # QoS Traffic Rate see $limit_rate on http://nginx.org/en/docs/http/ngx_http_core_module.html
-      set $limit_rate $limit_rate_qos;
+      set $limit_rate $limit_rate_qos;
 
       # Allow Higher Traffic Rate from Approved User-Agents which do not support cookies (uses nginx Map)
-      if ($approved_scraper) {
-        set $limit_rate 65536;
-      }
+      if ($approved_scraper) {
+        set $limit_rate 65536;
+      }
 
       if ($denied_scraper) {
         set $limit_rate 512;
@@ -210,6 +413,11 @@ server {
         return 418;
       }
 
+      if ($censored_referer) {
+        set $limit_rate 512;
+        return 451 "Unavailable at OSMF Board request";
+      }
+
       # Strip any ?query parameters from urls
       set $args '';
 
@@ -217,4 +425,5 @@ server {
       proxy_set_header Cache-Control $limit_http_cache_control;
       proxy_set_header Pragma $limit_http_pragma;
     }
+<% end %>
 }
diff --git a/cookbooks/tilecache/templates/default/ohai.rb.erb b/cookbooks/tilecache/templates/default/ohai.rb.erb
new file mode 100644 (file)
index 0000000..5647a45
--- /dev/null
@@ -0,0 +1,40 @@
+Ohai.plugin(:TileCache) do
+  provides "tilecache"
+
+  def tile_siblings
+    recent = Time.now - 600
+    times = Hash.new
+
+    # Find performance reports for last few minutes
+    # Add up total time taken to download tile grouped by remote server
+    # Remove 1 second per successful time report (de-prioritise new servers)
+    # Add 10 seconds per failed time report request
+    Dir.glob("/srv/tilecache/data/**/tilecache-*.txt").each do |path|
+      if File.mtime(path) > recent
+        IO.readlines(path).reverse.take(20).each do |sample|
+          if sample =~ %r{^(\d+\.\d+),(\d+),https://([^/]+)/} then
+            time = Regexp.last_match(1).to_f
+            status = Regexp.last_match(2).to_i
+            host = Regexp.last_match(3)
+
+            if status == 200 then
+              times[host] = times.fetch(host, 0) + (time + 1) * (time + 1) - 1
+            else
+              times[host] = times.fetch(host, 0) + 10
+            end
+          end
+        end
+      end
+    end
+
+    # Sort time reports
+    # Strip to best 4 server names
+    times.to_a.sort_by(&:last).take(4).map(&:first)
+  end
+
+  collect_data(:default) do
+    tilecache Mash.new
+
+    tilecache[:tile_siblings] = tile_siblings
+  end
+end
index 08d22812dd075c4f319be896569416d202450aa6..a575bcb0b53346e3ab863a1d5cdeb93c66aa974f 100644 (file)
@@ -2,88 +2,6 @@ acl osmtile_thishost dstdomain <%= node.name %>
 acl osmtile_sites dstdomain <%= node.name %> a.tile.openstreetmap.org b.tile.openstreetmap.org c.tile.openstreetmap.org tile.openstreetmap.org a.tile.osm.org b.tile.osm.org c.tile.osm.org tile.osm.org
 acl osmtiles_png urlpath_regex .png$
 
-acl osmtileScrapers browser ^$
-acl osmtileScrapers browser ^MOBAC
-acl osmtileScrapers browser ^JTileDownloader
-acl osmtileScrapers browser ^Apache\-HttpClient
-acl osmtileScrapers browser ^Go-http-client\/
-acl osmtileScrapers browser ^Opera\/10\.00
-acl osmtileScrapers browser ^shipxy01
-# acl osmtileScrapers browser ^OsmAnd # Victor + Email. Whitelist for 1 week
-# acl osmtileScrapers browser ^apemap # CGI143 + Email. Whitelist for 1 week
-acl osmtileScrapers browser Firefox\/2\.0\.0\.11$
-acl osmtileScrapers browser Firefox\/3\.5\.7$
-acl osmtileScrapers browser Firefox\/3\.6$
-acl osmtileScrapers browser ^Mozilla\/4\.0$
-acl osmtileScrapers browser ^Mozilla\/5\.0$ # QLandkarte unwilling to set a real user-agent.
-acl osmtileScrapers browser ^Mozilla$ # Intentionally faked user-agent
-acl osmtileScrapers browser ^User\-Agent
-acl osmtileScrapers browser Firefox\/0\.8$
-acl osmtileScrapers browser Firefox\/1\.0$
-acl osmtileScrapers browser Firefox\/1\.0\.7$
-acl osmtileScrapers browser K\-Meleon\/1\.02$
-acl osmtileScrapers browser MSIE.7\.0.*Windows.NT.5\.1.*2\.0\.50727.$
-acl osmtileScrapers browser MSIE.5.5
-acl osmtileScrapers browser ^LoadOSM\.exe$
-acl osmtileScrapers browser ^app_name$
-acl osmtileScrapers browser ^osmdroid$ # app using osmdroid library not setting app-specific User-Agent
-# acl osmtileScrapers browser ^Mozilla/5\.0 \(Windows NT 5\.1\)$ # Faked User-Agent
-acl osmtileScrapers browser Firefox\/3\.0
-acl osmtileScrapers browser Firefox\/4\.0
-acl osmtileScrapers browser Firefox\/5\.0
-acl osmtileScrapers browser Firefox\/6\.0
-acl osmtileScrapers browser Firefox\/7\.0
-acl osmtileScrapers browser Firefox\/8\.0
-acl osmtileScrapers browser Firefox\/9\.0
-acl osmtileScrapers browser Firefox\/10\.0
-acl osmtileScrapers browser Firefox\/11\.0
-acl osmtileScrapers browser Firefox\/12\.0
-acl osmtileScrapers browser Firefox\/13\.0
-acl osmtileScrapers browser ^Python\-urllib\/
-acl osmtileScrapers browser ^python\-requests\/
-acl osmtileScrapers browser ^node\-fetch\/
-acl osmtileScrapers browser ^R$
-acl osmtileScrapers browser ^Java\/
-acl osmtileScrapers browser ^tiles$
-acl osmtileScrapers browser ^runtastic
-
-acl is_fake_browser browser Firefox\/3\.0
-acl is_fake_browser browser Firefox\/4\.0
-acl is_fake_browser browser Firefox\/5\.0
-acl is_fake_browser browser Firefox\/6\.0
-acl is_fake_browser browser Firefox\/7\.0
-acl is_fake_browser browser Firefox\/8\.0
-acl is_fake_browser browser Firefox\/9\.0
-acl is_fake_browser browser Firefox\/10\.0
-acl is_fake_browser browser Firefox\/11\.0
-acl is_fake_browser browser Firefox\/12\.0
-acl is_fake_browser browser Firefox\/13\.0
-
-http_access deny osmtile_sites osmtileScrapers
-
-acl osmtileOverusers referer_regex ^https?://pmap\.kuku\.lu/
-acl osmtileOverusers referer_regex ^https?://[^.]*\.pmap\.kuku\.lu/
-acl osmtileOverusers referer_regex ^https?://fastpokemap\.com/
-acl osmtileOverusers referer_regex ^https?://[^.]*\.fastpokemap\.com/
-acl osmtileOverusers referer_regex ^https?://pkget\.com/
-acl osmtileOverusers referer_regex ^https?://[^.]*\.pkget\.com/
-
-# Faked OSM referers
-acl osmtileOverusers referer_regex ^http://www\.openstreetmap\.org/?$
-acl osmtileOverusers referer_regex ^http://openstreetmap\.org/?$
-acl osmtileOverusers referer_regex ^http://www\.osm\.org/?$
-acl osmtileOverusers referer_regex ^http://osm\.org/?$
-
-http_access deny osmtile_sites osmtileOverusers
-
-# Delay pool when !has_referer and is_browser
-acl has_referer referer_regex .
-acl is_browser browser Chrome\/
-acl is_browser browser Firefox\/
-acl is_browser browser Trident\/
-acl is_browser browser Safari\/
-acl is_browser browser AppleWebKit\/
-
 acl whitelist_path urlpath_regex ^/cgi-bin/(export|debug)
 acl blacklist_path urlpath_regex ^/cgi-bin/
 acl blacklist_path urlpath_regex ^/MyAdmin/
@@ -117,16 +35,13 @@ acl tile_caches src <%= address %>
 <% end -%>
 <% end -%>
 
-# Siblings
-<% node[:tilecache][:tile_siblings].each do |sibling| -%>
-cache_peer <%= sibling %> sibling 3128 3130 weight=1500
-<% end -%>
-
 # Primary Parent
 <% if node[:squid][:version] < 4 -%>
 cache_peer <%= node[:tilecache][:tile_parent] %> parent 443 0 no-query originserver name=osmtileAccel login=PASS connect-timeout=120 no-digest weight=1000 ssl ssldomain=render.openstreetmap.org
-<% else -%>
+<% elsif node[:lsb][:release].to_f < 20.04 -%>
 cache_peer <%= node[:tilecache][:tile_parent] %> parent 443 0 no-query originserver name=osmtileAccel login=PASS connect-timeout=120 no-digest weight=1000 tls tlsdomain=render.openstreetmap.org
+<% else -%>
+cache_peer <%= node[:tilecache][:tile_parent] %> parent 443 0 no-query originserver name=osmtileAccel login=PASS connect-timeout=120 no-digest weight=1000 tls tlsdomain=render.openstreetmap.org tls-options=NORMAL:-VERS-TLS1.3
 <% end -%>
 cache_peer_access osmtileAccel allow osmtile_sites
 
@@ -134,55 +49,23 @@ cache_peer_access osmtileAccel allow osmtile_sites
 <% @renders.each do |renders| -%>
 <% if node[:squid][:version] < 4 -%>
 cache_peer <%= renders[:hostname] %>.render.openstreetmap.org parent 443 0 no-query originserver name=osmtileAccelBackup<%= renders[:hostname] %> login=PASS connect-timeout=60 no-digest weight=10 ssl ssldomain=render.openstreetmap.org
-<% else -%>
+<% elsif node[:lsb][:release].to_f < 20.04 -%>
 cache_peer <%= renders[:hostname] %>.render.openstreetmap.org parent 443 0 no-query originserver name=osmtileAccelBackup<%= renders[:hostname] %> login=PASS connect-timeout=60 no-digest weight=10 tls tlsdomain=render.openstreetmap.org
+<% else -%>
+cache_peer <%= renders[:hostname] %>.render.openstreetmap.org parent 443 0 no-query originserver name=osmtileAccelBackup<%= renders[:hostname] %> login=PASS connect-timeout=60 no-digest weight=10 tls tlsdomain=render.openstreetmap.org tls-options=NORMAL:-VERS-TLS1.3
 <% end -%>
 cache_peer_access osmtileAccelBackup<%= renders[:hostname] %> allow osmtile_sites
 <% end -%>
 
 # ----------------------------------
-# Create an unlimited pool for cache IP addresses
-acl pool_unlimited src 127.0.0.1
-<% @caches.each do |cache| -%>
-<% cache.ipaddresses(:family => :inet, :role => :external).sort.each do |address| -%>
-acl pool_unlimited src <%= address %>
-<% end -%>
-<% end -%>
 
-# Juno Minsk office - me@komzpa.net
-acl pool_unlimited src 212.98.173.54
+<% if node[:squid][:version] < 4 -%>
+
+#Allow tile_caches HTCP access
+htcp_access allow tile_caches
 
 #Allow tile_caches ICP access
 icp_access allow tile_caches
-
-<% (0..127).each do |i| -%>
-acl pool_<%= sprintf("%03d", 2*i) %> src <%= 2*i %>.0.0.0/7
-<% end %>
-
-delay_pools 256
-delay_initial_bucket_level 25
-
-<% (1..256).each do |i| -%>
-delay_class <%= i %> 3
-<% end %>
-#bit mask
-# xxxxxxx- -------- xxxxxxxx xxxxxxxx
-
-# small pools for !has_referer && is_browser - designed to slow down anyone
-# using no-referer to bypass blocks due to abusive levels of use.
-<% (0..127).each do |i| -%>
-delay_access <%= i+1 %> allow pool_<%= sprintf("%03d", 2*i) %> !pool_unlimited is_fake_browser osmtile_sites
-delay_access <%= i+1 %> allow pool_<%= sprintf("%03d", 2*i) %> !pool_unlimited !has_referer is_browser osmtile_sites
-delay_access <%= i+1 %> deny all
-delay_parameters <%= i+1 %> -1/-1 <%= node[:tilecache][:net_bucket_refill] / 10 %>/<%= node[:tilecache][:net_bucket_size] / 10 %> <%= node[:tilecache][:ip_bucket_refill] / 10 %>/<%= node[:tilecache][:ip_bucket_size] / 10 %>
-<% end %>
-
-# bigger pools for users providing a referer (assuming it's not blocked)
-# or non-browser users.
-<% (0..127).each do |i| %>
-delay_access <%= i+129 %> allow pool_<%= sprintf("%03d", 2*i) %> !pool_unlimited osmtile_sites
-delay_access <%= i+129 %> deny all
-delay_parameters <%= i+129 %> -1/-1 <%= node[:tilecache][:net_bucket_refill] %>/<%= node[:tilecache][:net_bucket_size] %> <%= node[:tilecache][:ip_bucket_refill] %>/<%= node[:tilecache][:ip_bucket_size] %>
 <% end %>
 
 #----------------------------------
diff --git a/cookbooks/tilecache/templates/default/tilecache-curl-time-cleanup.erb b/cookbooks/tilecache/templates/default/tilecache-curl-time-cleanup.erb
new file mode 100644 (file)
index 0000000..3be4267
--- /dev/null
@@ -0,0 +1,3 @@
+#/bin/bash
+set -eu
+/usr/bin/find /srv/tilecache/data/ -type f -iname '*.txt' -mtime +7 -print0 | /usr/bin/xargs -0 -n 12 --no-run-if-empty -P 2 /usr/bin/xz -9e
diff --git a/cookbooks/tilecache/templates/default/tilecache-curl-time.erb b/cookbooks/tilecache/templates/default/tilecache-curl-time.erb
new file mode 100644 (file)
index 0000000..6abd2ea
--- /dev/null
@@ -0,0 +1,57 @@
+#!/bin/bash
+sleep $[ ( $RANDOM % 20 )  + 1 ]
+mkdir -p /srv/tilecache/data/$(date --utc "+%Y/%m")
+# localhost
+curl -w "@/srv/tilecache/tilecache-curl-time.txt" -o /dev/null -s -k -4 \
+--max-time 60 \
+'http://localhost:8080/19/262106/174485.png' \
+-H 'authority: c.tile.openstreetmap.org' \
+-H 'sec-fetch-dest: image' \
+-H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36' \
+-H 'dnt: 1' \
+-H 'accept: image/webp,image/apng,image/*,*/*;q=0.8' \
+-H 'sec-fetch-site: same-site' \
+-H 'sec-fetch-mode: no-cors' \
+-H 'referer: https://www.openstreetmap.org/' \
+-H 'accept-language: en-GB,en-US;q=0.9,en;q=0.8' \
+--compressed >> /srv/tilecache/data/$(date --utc "+%Y/%m")/localhost-<%= node.name.split(".").first %>-$(date --utc "+%Y-%m-%dT%H").txt
+# render
+<% @renders.each do |render| -%>
+<% if render.name != node.name -%>
+<% render.ipaddresses(:family => :inet, :role => :external).sort.each do |address| -%>
+    curl -w "@/srv/tilecache/tilecache-curl-time.txt" -o /dev/null -s -k -4 \
+    --max-time 60 \
+    'https://<%= render.name %>/19/262106/174485.png' \
+    -H 'authority: c.tile.openstreetmap.org' \
+    -H 'sec-fetch-dest: image' \
+    -H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36' \
+    -H 'dnt: 1' \
+    -H 'accept: image/webp,image/apng,image/*,*/*;q=0.8' \
+    -H 'sec-fetch-site: same-site' \
+    -H 'sec-fetch-mode: no-cors' \
+    -H 'referer: https://www.openstreetmap.org/' \
+    -H 'accept-language: en-GB,en-US;q=0.9,en;q=0.8' \
+    --compressed >> /srv/tilecache/data/$(date --utc "+%Y/%m")/render-<%= render.name.split(".").first %>-$(date --utc "+%Y-%m-%dT%H").txt
+<% end -%>
+<% end -%>
+<% end -%>
+# caches
+<% @caches.each do |cache| -%>
+<% if cache.name != node.name -%>
+<% cache.ipaddresses(:family => :inet, :role => :external).sort.each do |address| -%>
+    curl -w "@/srv/tilecache/tilecache-curl-time.txt" -o /dev/null -s -k -4 \
+    --max-time 60 \
+    'https://<%= cache.name %>/19/262106/174485.png' \
+    -H 'authority: c.tile.openstreetmap.org' \
+    -H 'sec-fetch-dest: image' \
+    -H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36' \
+    -H 'dnt: 1' \
+    -H 'accept: image/webp,image/apng,image/*,*/*;q=0.8' \
+    -H 'sec-fetch-site: same-site' \
+    -H 'sec-fetch-mode: no-cors' \
+    -H 'referer: https://www.openstreetmap.org/' \
+    -H 'accept-language: en-GB,en-US;q=0.9,en;q=0.8' \
+    --compressed >> /srv/tilecache/data/$(date --utc "+%Y/%m")/tilecache-<%= cache.name.split(".").first %>-$(date --utc "+%Y-%m-%dT%H").txt
+<% end -%>
+<% end -%>
+<% end -%>
index edc6e7e72e4def87898104c918ffdbb0dc84d021..8b4f91690ec6bcc01e94fd501570ef86407a7920 100644 (file)
 # limitations under the License.
 #
 
+include_recipe "git"
 include_recipe "tools"
 
 package %w[
   gcc
+  g++
   make
   autoconf
   automake
   libboost-filesystem-dev
-  libboost-system-dev
   libboost-program-options-dev
+  libboost-system-dev
 ]
 
 tilelog_source_directory = node[:tilelog][:source_directory]
@@ -40,7 +42,7 @@ git tilelog_source_directory do
   revision "live"
   user "root"
   group "root"
-  notifies :run, "execute[tilelog-autogen]", :immediate
+  notifies :run, "execute[tilelog-autogen]", :immediately
 end
 
 execute "tilelog-autogen" do
@@ -49,7 +51,7 @@ execute "tilelog-autogen" do
   cwd tilelog_source_directory
   user "root"
   group "root"
-  notifies :run, "execute[tilelog-configure]", :immediate
+  notifies :run, "execute[tilelog-configure]", :immediately
 end
 
 execute "tilelog-configure" do
@@ -58,7 +60,7 @@ execute "tilelog-configure" do
   cwd tilelog_source_directory
   user "root"
   group "root"
-  notifies :run, "execute[tilelog-build]", :immediate
+  notifies :run, "execute[tilelog-build]", :immediately
 end
 
 execute "tilelog-build" do
@@ -74,17 +76,18 @@ template "/usr/local/bin/tilelog" do
   source "tilelog.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   variables :analyze_bin => "#{tilelog_source_directory}/openstreetmap-tile-analyze",
             :input_dir => tilelog_input_directory,
             :output_dir => tilelog_output_directory
 end
 
-template "/etc/cron.d/tilelog" do
-  source "tilelog.cron.erb"
-  owner "root"
-  group "root"
-  mode 0o644
+cron_d "tilelog" do
+  minute "17"
+  hour "22"
+  user "www-data"
+  command "/usr/local/bin/tilelog"
+  mailto "zerebubuth@gmail.com"
 end
 
 # resources related to the output of the analysis and where it
@@ -92,5 +95,6 @@ end
 directory tilelog_output_directory do
   user "www-data"
   group "www-data"
-  mode 0o755
+  mode "755"
+  recursive true
 end
diff --git a/cookbooks/tilelog/templates/default/tilelog.cron.erb b/cookbooks/tilelog/templates/default/tilelog.cron.erb
deleted file mode 100644 (file)
index bd3278e..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-MAILTO=zerebubuth@gmail.com
-17 22 * * * www-data /usr/local/bin/tilelog
diff --git a/cookbooks/timescaledb/README.md b/cookbooks/timescaledb/README.md
new file mode 100644 (file)
index 0000000..f37c32e
--- /dev/null
@@ -0,0 +1,3 @@
+# TimescaleDB Cookbook
+
+This cookbook configures TimescaleDB.
diff --git a/cookbooks/timescaledb/attributes/default.rb b/cookbooks/timescaledb/attributes/default.rb
new file mode 100644 (file)
index 0000000..004dda6
--- /dev/null
@@ -0,0 +1,4 @@
+default[:timescaledb][:database_version] = "12"
+default[:timescaledb][:max_background_workers] = 8
+
+default[:apt][:sources] |= ["timescaledb"]
diff --git a/cookbooks/timescaledb/metadata.rb b/cookbooks/timescaledb/metadata.rb
new file mode 100644 (file)
index 0000000..9b8821a
--- /dev/null
@@ -0,0 +1,11 @@
+name              "timescaledb"
+maintainer        "OpenStreetMap Administrators"
+maintainer_email  "admins@openstreetmap.org"
+license           "Apache-2.0"
+description       "Installs and configures timescaledb"
+
+version           "1.0.0"
+supports          "ubuntu"
+depends           "apache"
+depends           "apt"
+depends           "postgresql"
diff --git a/cookbooks/timescaledb/recipes/default.rb b/cookbooks/timescaledb/recipes/default.rb
new file mode 100644 (file)
index 0000000..a987859
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# Cookbook:: timescaledb
+# Recipe:: default
+#
+# Copyright:: 2021, OpenStreetMap Foundation
+#
+# 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
+#
+#     https://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.
+#
+
+include_recipe "apt"
+
+database_version = node[:timescaledb][:database_version]
+
+package %W[
+  timescaledb-tools
+  timescaledb-2-postgresql-#{database_version}
+]
+
+node.default_unless[:postgresql][:versions] = []
+node.default[:postgresql][:versions] |= [database_version]
+node.default[:postgresql][:monitor_tables] = false
+node.default_unless[:postgresql][:settings][database_version][:shared_preload_libraries] = []
+node.default[:postgresql][:settings][database_version][:shared_preload_libraries] |= ["timescaledb"]
+node.default_unless[:postgresql][:settings][database_version][:customized_options] = {}
+node.default[:postgresql][:settings][database_version][:customized_options]["timescaledb.max_background_workers"] = node[:timescaledb][:max_background_workers]
+
+include_recipe "postgresql"
diff --git a/cookbooks/tools/attributes/default.rb b/cookbooks/tools/attributes/default.rb
new file mode 100644 (file)
index 0000000..b77bd1b
--- /dev/null
@@ -0,0 +1 @@
+default[:tools][:cron] = {}
index eaceb9d8eac55a7e9761391be0734a8e35efb137..ed0fe222a52f20ac0180df92a1480a1f6289d8b9 100644 (file)
@@ -36,6 +36,7 @@ package %w[
   lvm2
   rsyslog
   cron
+  locales-all
 ]
 
 service "rsyslog" do
@@ -48,16 +49,6 @@ package %w[mlocate nano whoopsie] do
   action :purge
 end
 
-# Remove screen-cleanup left behind by old release.
-file "/etc/init.d/screen-cleanup" do
-  action :delete
-end
-
-# Cleanup unused file
-file "/etc/systemd/system/cron.service.d/chef.conf" do
-  action :delete
-end
-
 # Configure cron to run in the local timezone of the machine
 systemd_service "cron-timezone" do
   service "cron"
@@ -67,7 +58,27 @@ systemd_service "cron-timezone" do
   only_if { node[:timezone] }
 end
 
+# Configure cron with lower cpu and IO priority
+if node[:tools][:cron][:load]
+  systemd_service "cron-load" do
+    service "cron"
+    dropin "load"
+    nice node[:tools][:cron][:load][:nice]
+    io_scheduling_class node[:tools][:cron][:load][:io_scheduling_class]
+    io_scheduling_priority node[:tools][:cron][:load][:io_scheduling_priority]
+    notifies :restart, "service[cron]"
+  end
+end
+
 # Make sure cron is running
 service "cron" do
   action [:enable, :start]
 end
+
+# Ubuntu MOTD adverts be-gone
+template "/etc/default/motd-news" do
+  source "motd-news.erb"
+  owner "root"
+  group "root"
+  mode "644"
+end
diff --git a/cookbooks/tools/templates/default/motd-news.erb b/cookbooks/tools/templates/default/motd-news.erb
new file mode 100644 (file)
index 0000000..ac0f13a
--- /dev/null
@@ -0,0 +1,21 @@
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Enable/disable the dynamic MOTD news service
+# This is a useful way to provide dynamic, informative
+# information pertinent to the users and administrators
+# of the local system
+ENABLED=0
+
+# Configure the source of dynamic MOTD news
+# White space separated list of 0 to many news services
+# For security reasons, these must be https
+# and have a valid certificate
+# Canonical runs a service at motd.ubuntu.com, and you
+# can easily run one too
+URLS="https://motd.ubuntu.com"
+
+# Specify the time in seconds, you're willing to wait for
+# dynamic MOTD news
+# Note that news messages are fetched in the background by
+# a systemd timer, so this should never block boot or login
+WAIT=5
diff --git a/cookbooks/trac/attributes/default.rb b/cookbooks/trac/attributes/default.rb
new file mode 100644 (file)
index 0000000..1683a2a
--- /dev/null
@@ -0,0 +1 @@
+default[:accounts][:users][:trac][:status] = :role
index 876457d095a0cd00af23b1ca6af2c88bdda4c42a..eabb60cc6866eb5cef99a6e42faa792f6a9907ec 100644 (file)
@@ -1,5 +1,3 @@
-#Trac really does not handle well being scraped.
+# This trac is no more. It has ceased to be.
 User-agent: *
-Disallow: /changeset
-Disallow: /changeset/
-Disallow: /wiki/
+Disallow: /
index 57fe9e358f1518472c3abd4a8e9b496c6cea429c..4c308e1e19c12c27a1817f2ee3c9ee7f6b4de16f 100644 (file)
@@ -6,4 +6,5 @@ description       "Installs and configures trac servers"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
index f7472131d398b1c98486e40dc78c70fae05bb1dd..070a520aa4ff3b9550bed4b3b4d0299dacac8d43 100644 (file)
 # limitations under the License.
 #
 
+include_recipe "accounts"
 include_recipe "apache"
 
 package %w[
   trac
-  trac-git
   ruby
 ]
 
 site_name = "trac.openstreetmap.org"
 site_directory = "/srv/#{site_name}"
 
+directory "/var/lib/trac" do
+  owner "trac"
+  group "trac"
+  mode "755"
+end
+
+execute "trac-initenv-#{site_name}" do
+  command "trac-admin /var/lib/trac initenv #{site_name} sqlite:db/trac.db"
+  user "trac"
+  group "trac"
+  not_if { ::File.exist?("/var/lib/trac/VERSION") }
+end
+
 template "/var/lib/trac/conf/trac.ini" do
   source "trac.ini.erb"
   owner "trac"
   group "www-data"
-  mode 0o644
+  mode "644"
   variables :name => site_name
 end
 
@@ -40,10 +53,10 @@ remote_directory "/var/lib/trac/htdocs" do
   source "htdocs"
   owner "trac"
   group "trac"
-  mode 0o755
+  mode "755"
   files_owner "trac"
   files_group "trac"
-  files_mode 0o644
+  files_mode "644"
   purge true
 end
 
@@ -51,10 +64,10 @@ remote_directory "/var/lib/trac/templates" do
   source "templates"
   owner "trac"
   group "trac"
-  mode 0o755
+  mode "755"
   files_owner "trac"
   files_group "trac"
-  files_mode 0o644
+  files_mode "644"
   purge true
 end
 
@@ -62,17 +75,21 @@ execute "trac-deploy-#{site_name}" do
   command "trac-admin /var/lib/trac deploy #{site_directory}"
   user "root"
   group "root"
-  not_if { File.exist?(site_directory) }
+  not_if { ::File.exist?(site_directory) }
 end
 
 cookbook_file "/usr/local/bin/trac-authenticate" do
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 apache_module "wsgi"
 
+apache_module "authnz_external" do
+  package "libapache2-mod-authnz-external"
+end
+
 ssl_certificate "trac.openstreetmap.org" do
   domains ["trac.openstreetmap.org", "trac.osm.org"]
   notifies :reload, "service[apache2]"
@@ -88,12 +105,12 @@ template "/etc/sudoers.d/trac" do
   source "sudoers.erb"
   owner "root"
   group "root"
-  mode 0o440
+  mode "440"
 end
 
 template "/etc/cron.daily/trac-backup" do
   source "backup.cron.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
index bc58ed276b8d07ff60fa7d701fd06b1c3c4627e3..d462cdd3639b146cbd0fefbc35ce3f8480fcc767 100644 (file)
@@ -1,6 +1,6 @@
 # DO NOT EDIT - This file is being maintained by Chef
 
-WSGIDaemonProcess <%= @name %> user=<%= @user %> group=<%= @group %> maximum-requests=5000 threads=25 inactivity-timeout=180
+WSGIDaemonProcess <%= @name %> user=<%= @user %> group=<%= @group %> processes=4 threads=8 restart-interval=3600 inactivity-timeout=180 graceful-timeout=60 maximum-requests=2000
 
 <VirtualHost *:80>
   ServerName <%= @name %>
@@ -54,6 +54,9 @@ WSGIDaemonProcess <%= @name %> user=<%= @user %> group=<%= @group %> maximum-req
 
   DefineExternalAuth osm pipe /usr/local/bin/trac-authenticate
 
+  # Disable /timeline for now
+  RedirectMatch 410 ^/timeline(.*)$
+
   <Location /login>
     AuthType Basic
     AuthName "OpenStreetMap Trac"
index e4e4bd8d6673fc738daccb7b95dd2802b5f6c53c..328d8e53cc7163e97d84b446407be375885caab1 100644 (file)
@@ -8,10 +8,9 @@ B=trac-$D.tar.gz
 
 trac-admin /var/lib/trac hotcopy $T/trac-$D > /dev/null
 
-export GZIP="--rsyncable -9"
 export RSYNC_RSH="ssh -ax"
 
-nice tar --create --gzip --directory=$T --file=$T/$B trac-$D
+nice tar --create --directory=$T trac-$D | nice gzip --rsyncable -9 > $T/$B
 nice rsync --preallocate --fuzzy $T/$B backup::backup
 
 rm -rf $T
index 79890cbdb18361c460376b9d5f95c726bfe1c5e2..7c995d9d818b65c54deb345986ce2a46cc8742a7 100644 (file)
@@ -1,4 +1,6 @@
 default[:web][:base_directory] = "/srv/www.openstreetmap.org"
-default[:web][:pid_directory] = "/var/run/web"
+default[:web][:pid_directory] = "/run/web"
 default[:web][:log_directory] = "/var/log/web"
 default[:web][:primary_cluster] = false
+
+default[:accounts][:users][:rails][:status] = :role
diff --git a/cookbooks/web/files/default/static/openlayers/OpenLayers.js b/cookbooks/web/files/default/static/openlayers/OpenLayers.js
new file mode 100644 (file)
index 0000000..ad5df5a
--- /dev/null
@@ -0,0 +1,1422 @@
+/*
+
+  OpenLayers.js -- OpenLayers Map Viewer Library
+
+  Copyright (c) 2006-2012 by OpenLayers Contributors
+  Published under the 2-clause BSD license.
+  See http://openlayers.org/dev/license.txt for the full text of the license, and http://openlayers.org/dev/authors.txt for full list of contributors.
+
+  Includes compressed code under the following licenses:
+
+  (For uncompressed versions of the code used, please see the
+  OpenLayers Github repository: <https://github.com/openlayers/openlayers>)
+
+*/
+
+/**
+ * Contains XMLHttpRequest.js <http://code.google.com/p/xmlhttprequest/>
+ * Copyright 2007 Sergey Ilinsky (http://www.ilinsky.com)
+ *
+ * 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
+ */
+
+/**
+ * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is
+ * Copyright (c) 2006, Yahoo! Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use of this software in source and binary forms, with or
+ * without modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of Yahoo! Inc. nor the names of its contributors may be
+ *   used to endorse or promote products derived from this software without
+ *   specific prior written permission of Yahoo! Inc.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+var OpenLayers={VERSION_NUMBER:"Release 2.12",singleFile:true,_getScriptLocation:(function(){var r=new RegExp("(^|(.*?\\/))(OpenLayers[^\\/]*?\\.js)(\\?|$)"),s=document.getElementsByTagName('script'),src,m,l="";for(var i=0,len=s.length;i<len;i++){src=s[i].getAttribute('src');if(src){m=src.match(r);if(m){l=m[1];break;}}}
+return(function(){return l;});})(),ImgPath:''};OpenLayers.String={startsWith:function(str,sub){return(str.indexOf(sub)==0);},contains:function(str,sub){return(str.indexOf(sub)!=-1);},trim:function(str){return str.replace(/^\s\s*/,'').replace(/\s\s*$/,'');},camelize:function(str){var oStringList=str.split('-');var camelizedString=oStringList[0];for(var i=1,len=oStringList.length;i<len;i++){var s=oStringList[i];camelizedString+=s.charAt(0).toUpperCase()+s.substring(1);}
+return camelizedString;},format:function(template,context,args){if(!context){context=window;}
+var replacer=function(str,match){var replacement;var subs=match.split(/\.+/);for(var i=0;i<subs.length;i++){if(i==0){replacement=context;}
+replacement=replacement[subs[i]];}
+if(typeof replacement=="function"){replacement=args?replacement.apply(null,args):replacement();}
+if(typeof replacement=='undefined'){return'undefined';}else{return replacement;}};return template.replace(OpenLayers.String.tokenRegEx,replacer);},tokenRegEx:/\$\{([\w.]+?)\}/g,numberRegEx:/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/,isNumeric:function(value){return OpenLayers.String.numberRegEx.test(value);},numericIf:function(value){return OpenLayers.String.isNumeric(value)?parseFloat(value):value;}};OpenLayers.Number={decimalSeparator:".",thousandsSeparator:",",limitSigDigs:function(num,sig){var fig=0;if(sig>0){fig=parseFloat(num.toPrecision(sig));}
+return fig;},format:function(num,dec,tsep,dsep){dec=(typeof dec!="undefined")?dec:0;tsep=(typeof tsep!="undefined")?tsep:OpenLayers.Number.thousandsSeparator;dsep=(typeof dsep!="undefined")?dsep:OpenLayers.Number.decimalSeparator;if(dec!=null){num=parseFloat(num.toFixed(dec));}
+var parts=num.toString().split(".");if(parts.length==1&&dec==null){dec=0;}
+var integer=parts[0];if(tsep){var thousands=/(-?[0-9]+)([0-9]{3})/;while(thousands.test(integer)){integer=integer.replace(thousands,"$1"+tsep+"$2");}}
+var str;if(dec==0){str=integer;}else{var rem=parts.length>1?parts[1]:"0";if(dec!=null){rem=rem+new Array(dec-rem.length+1).join("0");}
+str=integer+dsep+rem;}
+return str;}};OpenLayers.Function={bind:function(func,object){var args=Array.prototype.slice.apply(arguments,[2]);return function(){var newArgs=args.concat(Array.prototype.slice.apply(arguments,[0]));return func.apply(object,newArgs);};},bindAsEventListener:function(func,object){return function(event){return func.call(object,event||window.event);};},False:function(){return false;},True:function(){return true;},Void:function(){}};OpenLayers.Array={filter:function(array,callback,caller){var selected=[];if(Array.prototype.filter){selected=array.filter(callback,caller);}else{var len=array.length;if(typeof callback!="function"){throw new TypeError();}
+for(var i=0;i<len;i++){if(i in array){var val=array[i];if(callback.call(caller,val,i,array)){selected.push(val);}}}}
+return selected;}};OpenLayers.Class=function(){var len=arguments.length;var P=arguments[0];var F=arguments[len-1];var C=typeof F.initialize=="function"?F.initialize:function(){P.prototype.initialize.apply(this,arguments);};if(len>1){var newArgs=[C,P].concat(Array.prototype.slice.call(arguments).slice(1,len-1),F);OpenLayers.inherit.apply(null,newArgs);}else{C.prototype=F;}
+return C;};OpenLayers.inherit=function(C,P){var F=function(){};F.prototype=P.prototype;C.prototype=new F;var i,l,o;for(i=2,l=arguments.length;i<l;i++){o=arguments[i];if(typeof o==="function"){o=o.prototype;}
+OpenLayers.Util.extend(C.prototype,o);}};OpenLayers.Util=OpenLayers.Util||{};OpenLayers.Util.extend=function(destination,source){destination=destination||{};if(source){for(var property in source){var value=source[property];if(value!==undefined){destination[property]=value;}}
+var sourceIsEvt=typeof window.Event=="function"&&source instanceof window.Event;if(!sourceIsEvt&&source.hasOwnProperty&&source.hasOwnProperty("toString")){destination.toString=source.toString;}}
+return destination;};OpenLayers.Bounds=OpenLayers.Class({left:null,bottom:null,right:null,top:null,centerLonLat:null,initialize:function(left,bottom,right,top){if(OpenLayers.Util.isArray(left)){top=left[3];right=left[2];bottom=left[1];left=left[0];}
+if(left!=null){this.left=OpenLayers.Util.toFloat(left);}
+if(bottom!=null){this.bottom=OpenLayers.Util.toFloat(bottom);}
+if(right!=null){this.right=OpenLayers.Util.toFloat(right);}
+if(top!=null){this.top=OpenLayers.Util.toFloat(top);}},clone:function(){return new OpenLayers.Bounds(this.left,this.bottom,this.right,this.top);},equals:function(bounds){var equals=false;if(bounds!=null){equals=((this.left==bounds.left)&&(this.right==bounds.right)&&(this.top==bounds.top)&&(this.bottom==bounds.bottom));}
+return equals;},toString:function(){return[this.left,this.bottom,this.right,this.top].join(",");},toArray:function(reverseAxisOrder){if(reverseAxisOrder===true){return[this.bottom,this.left,this.top,this.right];}else{return[this.left,this.bottom,this.right,this.top];}},toBBOX:function(decimal,reverseAxisOrder){if(decimal==null){decimal=6;}
+var mult=Math.pow(10,decimal);var xmin=Math.round(this.left*mult)/mult;var ymin=Math.round(this.bottom*mult)/mult;var xmax=Math.round(this.right*mult)/mult;var ymax=Math.round(this.top*mult)/mult;if(reverseAxisOrder===true){return ymin+","+xmin+","+ymax+","+xmax;}else{return xmin+","+ymin+","+xmax+","+ymax;}},toGeometry:function(){return new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing([new OpenLayers.Geometry.Point(this.left,this.bottom),new OpenLayers.Geometry.Point(this.right,this.bottom),new OpenLayers.Geometry.Point(this.right,this.top),new OpenLayers.Geometry.Point(this.left,this.top)])]);},getWidth:function(){return(this.right-this.left);},getHeight:function(){return(this.top-this.bottom);},getSize:function(){return new OpenLayers.Size(this.getWidth(),this.getHeight());},getCenterPixel:function(){return new OpenLayers.Pixel((this.left+this.right)/2,(this.bottom+this.top)/2);},getCenterLonLat:function(){if(!this.centerLonLat){this.centerLonLat=new OpenLayers.LonLat((this.left+this.right)/2,(this.bottom+this.top)/2);}
+return this.centerLonLat;},scale:function(ratio,origin){if(origin==null){origin=this.getCenterLonLat();}
+var origx,origy;if(origin.CLASS_NAME=="OpenLayers.LonLat"){origx=origin.lon;origy=origin.lat;}else{origx=origin.x;origy=origin.y;}
+var left=(this.left-origx)*ratio+origx;var bottom=(this.bottom-origy)*ratio+origy;var right=(this.right-origx)*ratio+origx;var top=(this.top-origy)*ratio+origy;return new OpenLayers.Bounds(left,bottom,right,top);},add:function(x,y){if((x==null)||(y==null)){throw new TypeError('Bounds.add cannot receive null values');}
+return new OpenLayers.Bounds(this.left+x,this.bottom+y,this.right+x,this.top+y);},extend:function(object){var bounds=null;if(object){switch(object.CLASS_NAME){case"OpenLayers.LonLat":bounds=new OpenLayers.Bounds(object.lon,object.lat,object.lon,object.lat);break;case"OpenLayers.Geometry.Point":bounds=new OpenLayers.Bounds(object.x,object.y,object.x,object.y);break;case"OpenLayers.Bounds":bounds=object;break;}
+if(bounds){this.centerLonLat=null;if((this.left==null)||(bounds.left<this.left)){this.left=bounds.left;}
+if((this.bottom==null)||(bounds.bottom<this.bottom)){this.bottom=bounds.bottom;}
+if((this.right==null)||(bounds.right>this.right)){this.right=bounds.right;}
+if((this.top==null)||(bounds.top>this.top)){this.top=bounds.top;}}}},containsLonLat:function(ll,options){if(typeof options==="boolean"){options={inclusive:options};}
+options=options||{};var contains=this.contains(ll.lon,ll.lat,options.inclusive),worldBounds=options.worldBounds;if(worldBounds&&!contains){var worldWidth=worldBounds.getWidth();var worldCenterX=(worldBounds.left+worldBounds.right)/2;var worldsAway=Math.round((ll.lon-worldCenterX)/worldWidth);contains=this.containsLonLat({lon:ll.lon-worldsAway*worldWidth,lat:ll.lat},{inclusive:options.inclusive});}
+return contains;},containsPixel:function(px,inclusive){return this.contains(px.x,px.y,inclusive);},contains:function(x,y,inclusive){if(inclusive==null){inclusive=true;}
+if(x==null||y==null){return false;}
+x=OpenLayers.Util.toFloat(x);y=OpenLayers.Util.toFloat(y);var contains=false;if(inclusive){contains=((x>=this.left)&&(x<=this.right)&&(y>=this.bottom)&&(y<=this.top));}else{contains=((x>this.left)&&(x<this.right)&&(y>this.bottom)&&(y<this.top));}
+return contains;},intersectsBounds:function(bounds,options){if(typeof options==="boolean"){options={inclusive:options};}
+options=options||{};if(options.worldBounds){var self=this.wrapDateLine(options.worldBounds);bounds=bounds.wrapDateLine(options.worldBounds);}else{self=this;}
+if(options.inclusive==null){options.inclusive=true;}
+var intersects=false;var mightTouch=(self.left==bounds.right||self.right==bounds.left||self.top==bounds.bottom||self.bottom==bounds.top);if(options.inclusive||!mightTouch){var inBottom=(((bounds.bottom>=self.bottom)&&(bounds.bottom<=self.top))||((self.bottom>=bounds.bottom)&&(self.bottom<=bounds.top)));var inTop=(((bounds.top>=self.bottom)&&(bounds.top<=self.top))||((self.top>bounds.bottom)&&(self.top<bounds.top)));var inLeft=(((bounds.left>=self.left)&&(bounds.left<=self.right))||((self.left>=bounds.left)&&(self.left<=bounds.right)));var inRight=(((bounds.right>=self.left)&&(bounds.right<=self.right))||((self.right>=bounds.left)&&(self.right<=bounds.right)));intersects=((inBottom||inTop)&&(inLeft||inRight));}
+if(options.worldBounds&&!intersects){var world=options.worldBounds;var width=world.getWidth();var selfCrosses=!world.containsBounds(self);var boundsCrosses=!world.containsBounds(bounds);if(selfCrosses&&!boundsCrosses){bounds=bounds.add(-width,0);intersects=self.intersectsBounds(bounds,{inclusive:options.inclusive});}else if(boundsCrosses&&!selfCrosses){self=self.add(-width,0);intersects=bounds.intersectsBounds(self,{inclusive:options.inclusive});}}
+return intersects;},containsBounds:function(bounds,partial,inclusive){if(partial==null){partial=false;}
+if(inclusive==null){inclusive=true;}
+var bottomLeft=this.contains(bounds.left,bounds.bottom,inclusive);var bottomRight=this.contains(bounds.right,bounds.bottom,inclusive);var topLeft=this.contains(bounds.left,bounds.top,inclusive);var topRight=this.contains(bounds.right,bounds.top,inclusive);return(partial)?(bottomLeft||bottomRight||topLeft||topRight):(bottomLeft&&bottomRight&&topLeft&&topRight);},determineQuadrant:function(lonlat){var quadrant="";var center=this.getCenterLonLat();quadrant+=(lonlat.lat<center.lat)?"b":"t";quadrant+=(lonlat.lon<center.lon)?"l":"r";return quadrant;},transform:function(source,dest){this.centerLonLat=null;var ll=OpenLayers.Projection.transform({'x':this.left,'y':this.bottom},source,dest);var lr=OpenLayers.Projection.transform({'x':this.right,'y':this.bottom},source,dest);var ul=OpenLayers.Projection.transform({'x':this.left,'y':this.top},source,dest);var ur=OpenLayers.Projection.transform({'x':this.right,'y':this.top},source,dest);this.left=Math.min(ll.x,ul.x);this.bottom=Math.min(ll.y,lr.y);this.right=Math.max(lr.x,ur.x);this.top=Math.max(ul.y,ur.y);return this;},wrapDateLine:function(maxExtent,options){options=options||{};var leftTolerance=options.leftTolerance||0;var rightTolerance=options.rightTolerance||0;var newBounds=this.clone();if(maxExtent){var width=maxExtent.getWidth();while(newBounds.left<maxExtent.left&&newBounds.right-rightTolerance<=maxExtent.left){newBounds=newBounds.add(width,0);}
+while(newBounds.left+leftTolerance>=maxExtent.right&&newBounds.right>maxExtent.right){newBounds=newBounds.add(-width,0);}
+var newLeft=newBounds.left+leftTolerance;if(newLeft<maxExtent.right&&newLeft>maxExtent.left&&newBounds.right-rightTolerance>maxExtent.right){newBounds=newBounds.add(-width,0);}}
+return newBounds;},CLASS_NAME:"OpenLayers.Bounds"});OpenLayers.Bounds.fromString=function(str,reverseAxisOrder){var bounds=str.split(",");return OpenLayers.Bounds.fromArray(bounds,reverseAxisOrder);};OpenLayers.Bounds.fromArray=function(bbox,reverseAxisOrder){return reverseAxisOrder===true?new OpenLayers.Bounds(bbox[1],bbox[0],bbox[3],bbox[2]):new OpenLayers.Bounds(bbox[0],bbox[1],bbox[2],bbox[3]);};OpenLayers.Bounds.fromSize=function(size){return new OpenLayers.Bounds(0,size.h,size.w,0);};OpenLayers.Bounds.oppositeQuadrant=function(quadrant){var opp="";opp+=(quadrant.charAt(0)=='t')?'b':'t';opp+=(quadrant.charAt(1)=='l')?'r':'l';return opp;};OpenLayers.Element={visible:function(element){return OpenLayers.Util.getElement(element).style.display!='none';},toggle:function(){for(var i=0,len=arguments.length;i<len;i++){var element=OpenLayers.Util.getElement(arguments[i]);var display=OpenLayers.Element.visible(element)?'none':'';element.style.display=display;}},remove:function(element){element=OpenLayers.Util.getElement(element);element.parentNode.removeChild(element);},getHeight:function(element){element=OpenLayers.Util.getElement(element);return element.offsetHeight;},hasClass:function(element,name){var names=element.className;return(!!names&&new RegExp("(^|\\s)"+name+"(\\s|$)").test(names));},addClass:function(element,name){if(!OpenLayers.Element.hasClass(element,name)){element.className+=(element.className?" ":"")+name;}
+return element;},removeClass:function(element,name){var names=element.className;if(names){element.className=OpenLayers.String.trim(names.replace(new RegExp("(^|\\s+)"+name+"(\\s+|$)")," "));}
+return element;},toggleClass:function(element,name){if(OpenLayers.Element.hasClass(element,name)){OpenLayers.Element.removeClass(element,name);}else{OpenLayers.Element.addClass(element,name);}
+return element;},getStyle:function(element,style){element=OpenLayers.Util.getElement(element);var value=null;if(element&&element.style){value=element.style[OpenLayers.String.camelize(style)];if(!value){if(document.defaultView&&document.defaultView.getComputedStyle){var css=document.defaultView.getComputedStyle(element,null);value=css?css.getPropertyValue(style):null;}else if(element.currentStyle){value=element.currentStyle[OpenLayers.String.camelize(style)];}}
+var positions=['left','top','right','bottom'];if(window.opera&&(OpenLayers.Util.indexOf(positions,style)!=-1)&&(OpenLayers.Element.getStyle(element,'position')=='static')){value='auto';}}
+return value=='auto'?null:value;}};OpenLayers.LonLat=OpenLayers.Class({lon:0.0,lat:0.0,initialize:function(lon,lat){if(OpenLayers.Util.isArray(lon)){lat=lon[1];lon=lon[0];}
+this.lon=OpenLayers.Util.toFloat(lon);this.lat=OpenLayers.Util.toFloat(lat);},toString:function(){return("lon="+this.lon+",lat="+this.lat);},toShortString:function(){return(this.lon+", "+this.lat);},clone:function(){return new OpenLayers.LonLat(this.lon,this.lat);},add:function(lon,lat){if((lon==null)||(lat==null)){throw new TypeError('LonLat.add cannot receive null values');}
+return new OpenLayers.LonLat(this.lon+OpenLayers.Util.toFloat(lon),this.lat+OpenLayers.Util.toFloat(lat));},equals:function(ll){var equals=false;if(ll!=null){equals=((this.lon==ll.lon&&this.lat==ll.lat)||(isNaN(this.lon)&&isNaN(this.lat)&&isNaN(ll.lon)&&isNaN(ll.lat)));}
+return equals;},transform:function(source,dest){var point=OpenLayers.Projection.transform({'x':this.lon,'y':this.lat},source,dest);this.lon=point.x;this.lat=point.y;return this;},wrapDateLine:function(maxExtent){var newLonLat=this.clone();if(maxExtent){while(newLonLat.lon<maxExtent.left){newLonLat.lon+=maxExtent.getWidth();}
+while(newLonLat.lon>maxExtent.right){newLonLat.lon-=maxExtent.getWidth();}}
+return newLonLat;},CLASS_NAME:"OpenLayers.LonLat"});OpenLayers.LonLat.fromString=function(str){var pair=str.split(",");return new OpenLayers.LonLat(pair[0],pair[1]);};OpenLayers.LonLat.fromArray=function(arr){var gotArr=OpenLayers.Util.isArray(arr),lon=gotArr&&arr[0],lat=gotArr&&arr[1];return new OpenLayers.LonLat(lon,lat);};OpenLayers.Pixel=OpenLayers.Class({x:0.0,y:0.0,initialize:function(x,y){this.x=parseFloat(x);this.y=parseFloat(y);},toString:function(){return("x="+this.x+",y="+this.y);},clone:function(){return new OpenLayers.Pixel(this.x,this.y);},equals:function(px){var equals=false;if(px!=null){equals=((this.x==px.x&&this.y==px.y)||(isNaN(this.x)&&isNaN(this.y)&&isNaN(px.x)&&isNaN(px.y)));}
+return equals;},distanceTo:function(px){return Math.sqrt(Math.pow(this.x-px.x,2)+
+Math.pow(this.y-px.y,2));},add:function(x,y){if((x==null)||(y==null)){throw new TypeError('Pixel.add cannot receive null values');}
+return new OpenLayers.Pixel(this.x+x,this.y+y);},offset:function(px){var newPx=this.clone();if(px){newPx=this.add(px.x,px.y);}
+return newPx;},CLASS_NAME:"OpenLayers.Pixel"});OpenLayers.Size=OpenLayers.Class({w:0.0,h:0.0,initialize:function(w,h){this.w=parseFloat(w);this.h=parseFloat(h);},toString:function(){return("w="+this.w+",h="+this.h);},clone:function(){return new OpenLayers.Size(this.w,this.h);},equals:function(sz){var equals=false;if(sz!=null){equals=((this.w==sz.w&&this.h==sz.h)||(isNaN(this.w)&&isNaN(this.h)&&isNaN(sz.w)&&isNaN(sz.h)));}
+return equals;},CLASS_NAME:"OpenLayers.Size"});OpenLayers.Console={log:function(){},debug:function(){},info:function(){},warn:function(){},error:function(){},userError:function(error){alert(error);},assert:function(){},dir:function(){},dirxml:function(){},trace:function(){},group:function(){},groupEnd:function(){},time:function(){},timeEnd:function(){},profile:function(){},profileEnd:function(){},count:function(){},CLASS_NAME:"OpenLayers.Console"};(function(){var scripts=document.getElementsByTagName("script");for(var i=0,len=scripts.length;i<len;++i){if(scripts[i].src.indexOf("firebug.js")!=-1){if(console){OpenLayers.Util.extend(OpenLayers.Console,console);break;}}}})();OpenLayers.Lang={code:null,defaultCode:"en",getCode:function(){if(!OpenLayers.Lang.code){OpenLayers.Lang.setCode();}
+return OpenLayers.Lang.code;},setCode:function(code){var lang;if(!code){code=(OpenLayers.BROWSER_NAME=="msie")?navigator.userLanguage:navigator.language;}
+var parts=code.split('-');parts[0]=parts[0].toLowerCase();if(typeof OpenLayers.Lang[parts[0]]=="object"){lang=parts[0];}
+if(parts[1]){var testLang=parts[0]+'-'+parts[1].toUpperCase();if(typeof OpenLayers.Lang[testLang]=="object"){lang=testLang;}}
+if(!lang){OpenLayers.Console.warn('Failed to find OpenLayers.Lang.'+parts.join("-")+' dictionary, falling back to default language');lang=OpenLayers.Lang.defaultCode;}
+OpenLayers.Lang.code=lang;},translate:function(key,context){var dictionary=OpenLayers.Lang[OpenLayers.Lang.getCode()];var message=dictionary&&dictionary[key];if(!message){message=key;}
+if(context){message=OpenLayers.String.format(message,context);}
+return message;}};OpenLayers.i18n=OpenLayers.Lang.translate;OpenLayers.Util=OpenLayers.Util||{};OpenLayers.Util.getElement=function(){var elements=[];for(var i=0,len=arguments.length;i<len;i++){var element=arguments[i];if(typeof element=='string'){element=document.getElementById(element);}
+if(arguments.length==1){return element;}
+elements.push(element);}
+return elements;};OpenLayers.Util.isElement=function(o){return!!(o&&o.nodeType===1);};OpenLayers.Util.isArray=function(a){return(Object.prototype.toString.call(a)==='[object Array]');};if(typeof window.$==="undefined"){window.$=OpenLayers.Util.getElement;}
+OpenLayers.Util.removeItem=function(array,item){for(var i=array.length-1;i>=0;i--){if(array[i]==item){array.splice(i,1);}}
+return array;};OpenLayers.Util.indexOf=function(array,obj){if(typeof array.indexOf=="function"){return array.indexOf(obj);}else{for(var i=0,len=array.length;i<len;i++){if(array[i]==obj){return i;}}
+return-1;}};OpenLayers.Util.modifyDOMElement=function(element,id,px,sz,position,border,overflow,opacity){if(id){element.id=id;}
+if(px){element.style.left=px.x+"px";element.style.top=px.y+"px";}
+if(sz){element.style.width=sz.w+"px";element.style.height=sz.h+"px";}
+if(position){element.style.position=position;}
+if(border){element.style.border=border;}
+if(overflow){element.style.overflow=overflow;}
+if(parseFloat(opacity)>=0.0&&parseFloat(opacity)<1.0){element.style.filter='alpha(opacity='+(opacity*100)+')';element.style.opacity=opacity;}else if(parseFloat(opacity)==1.0){element.style.filter='';element.style.opacity='';}};OpenLayers.Util.createDiv=function(id,px,sz,imgURL,position,border,overflow,opacity){var dom=document.createElement('div');if(imgURL){dom.style.backgroundImage='url('+imgURL+')';}
+if(!id){id=OpenLayers.Util.createUniqueID("OpenLayersDiv");}
+if(!position){position="absolute";}
+OpenLayers.Util.modifyDOMElement(dom,id,px,sz,position,border,overflow,opacity);return dom;};OpenLayers.Util.createImage=function(id,px,sz,imgURL,position,border,opacity,delayDisplay){var image=document.createElement("img");if(!id){id=OpenLayers.Util.createUniqueID("OpenLayersDiv");}
+if(!position){position="relative";}
+OpenLayers.Util.modifyDOMElement(image,id,px,sz,position,border,null,opacity);if(delayDisplay){image.style.display="none";function display(){image.style.display="";OpenLayers.Event.stopObservingElement(image);}
+OpenLayers.Event.observe(image,"load",display);OpenLayers.Event.observe(image,"error",display);}
+image.style.alt=id;image.galleryImg="no";if(imgURL){image.src=imgURL;}
+return image;};OpenLayers.IMAGE_RELOAD_ATTEMPTS=0;OpenLayers.Util.alphaHackNeeded=null;OpenLayers.Util.alphaHack=function(){if(OpenLayers.Util.alphaHackNeeded==null){var arVersion=navigator.appVersion.split("MSIE");var version=parseFloat(arVersion[1]);var filter=false;try{filter=!!(document.body.filters);}catch(e){}
+OpenLayers.Util.alphaHackNeeded=(filter&&(version>=5.5)&&(version<7));}
+return OpenLayers.Util.alphaHackNeeded;};OpenLayers.Util.modifyAlphaImageDiv=function(div,id,px,sz,imgURL,position,border,sizing,opacity){OpenLayers.Util.modifyDOMElement(div,id,px,sz,position,null,null,opacity);var img=div.childNodes[0];if(imgURL){img.src=imgURL;}
+OpenLayers.Util.modifyDOMElement(img,div.id+"_innerImage",null,sz,"relative",border);if(OpenLayers.Util.alphaHack()){if(div.style.display!="none"){div.style.display="inline-block";}
+if(sizing==null){sizing="scale";}
+div.style.filter="progid:DXImageTransform.Microsoft"+".AlphaImageLoader(src='"+img.src+"', "+"sizingMethod='"+sizing+"')";if(parseFloat(div.style.opacity)>=0.0&&parseFloat(div.style.opacity)<1.0){div.style.filter+=" alpha(opacity="+div.style.opacity*100+")";}
+img.style.filter="alpha(opacity=0)";}};OpenLayers.Util.createAlphaImageDiv=function(id,px,sz,imgURL,position,border,sizing,opacity,delayDisplay){var div=OpenLayers.Util.createDiv();var img=OpenLayers.Util.createImage(null,null,null,null,null,null,null,delayDisplay);img.className="olAlphaImg";div.appendChild(img);OpenLayers.Util.modifyAlphaImageDiv(div,id,px,sz,imgURL,position,border,sizing,opacity);return div;};OpenLayers.Util.upperCaseObject=function(object){var uObject={};for(var key in object){uObject[key.toUpperCase()]=object[key];}
+return uObject;};OpenLayers.Util.applyDefaults=function(to,from){to=to||{};var fromIsEvt=typeof window.Event=="function"&&from instanceof window.Event;for(var key in from){if(to[key]===undefined||(!fromIsEvt&&from.hasOwnProperty&&from.hasOwnProperty(key)&&!to.hasOwnProperty(key))){to[key]=from[key];}}
+if(!fromIsEvt&&from&&from.hasOwnProperty&&from.hasOwnProperty('toString')&&!to.hasOwnProperty('toString')){to.toString=from.toString;}
+return to;};OpenLayers.Util.getParameterString=function(params){var paramsArray=[];for(var key in params){var value=params[key];if((value!=null)&&(typeof value!='function')){var encodedValue;if(typeof value=='object'&&value.constructor==Array){var encodedItemArray=[];var item;for(var itemIndex=0,len=value.length;itemIndex<len;itemIndex++){item=value[itemIndex];encodedItemArray.push(encodeURIComponent((item===null||item===undefined)?"":item));}
+encodedValue=encodedItemArray.join(",");}
+else{encodedValue=encodeURIComponent(value);}
+paramsArray.push(encodeURIComponent(key)+"="+encodedValue);}}
+return paramsArray.join("&");};OpenLayers.Util.urlAppend=function(url,paramStr){var newUrl=url;if(paramStr){var parts=(url+" ").split(/[?&]/);newUrl+=(parts.pop()===" "?paramStr:parts.length?"&"+paramStr:"?"+paramStr);}
+return newUrl;};OpenLayers.Util.getImagesLocation=function(){return OpenLayers.ImgPath||(OpenLayers._getScriptLocation()+"img/");};OpenLayers.Util.getImageLocation=function(image){return OpenLayers.Util.getImagesLocation()+image;};OpenLayers.Util.Try=function(){var returnValue=null;for(var i=0,len=arguments.length;i<len;i++){var lambda=arguments[i];try{returnValue=lambda();break;}catch(e){}}
+return returnValue;};OpenLayers.Util.getXmlNodeValue=function(node){var val=null;OpenLayers.Util.Try(function(){val=node.text;if(!val){val=node.textContent;}
+if(!val){val=node.firstChild.nodeValue;}},function(){val=node.textContent;});return val;};OpenLayers.Util.mouseLeft=function(evt,div){var target=(evt.relatedTarget)?evt.relatedTarget:evt.toElement;while(target!=div&&target!=null){target=target.parentNode;}
+return(target!=div);};OpenLayers.Util.DEFAULT_PRECISION=14;OpenLayers.Util.toFloat=function(number,precision){if(precision==null){precision=OpenLayers.Util.DEFAULT_PRECISION;}
+if(typeof number!=="number"){number=parseFloat(number);}
+return precision===0?number:parseFloat(number.toPrecision(precision));};OpenLayers.Util.rad=function(x){return x*Math.PI/180;};OpenLayers.Util.deg=function(x){return x*180/Math.PI;};OpenLayers.Util.VincentyConstants={a:6378137,b:6356752.3142,f:1/298.257223563};OpenLayers.Util.distVincenty=function(p1,p2){var ct=OpenLayers.Util.VincentyConstants;var a=ct.a,b=ct.b,f=ct.f;var L=OpenLayers.Util.rad(p2.lon-p1.lon);var U1=Math.atan((1-f)*Math.tan(OpenLayers.Util.rad(p1.lat)));var U2=Math.atan((1-f)*Math.tan(OpenLayers.Util.rad(p2.lat)));var sinU1=Math.sin(U1),cosU1=Math.cos(U1);var sinU2=Math.sin(U2),cosU2=Math.cos(U2);var lambda=L,lambdaP=2*Math.PI;var iterLimit=20;while(Math.abs(lambda-lambdaP)>1e-12&&--iterLimit>0){var sinLambda=Math.sin(lambda),cosLambda=Math.cos(lambda);var sinSigma=Math.sqrt((cosU2*sinLambda)*(cosU2*sinLambda)+
+(cosU1*sinU2-sinU1*cosU2*cosLambda)*(cosU1*sinU2-sinU1*cosU2*cosLambda));if(sinSigma==0){return 0;}
+var cosSigma=sinU1*sinU2+cosU1*cosU2*cosLambda;var sigma=Math.atan2(sinSigma,cosSigma);var alpha=Math.asin(cosU1*cosU2*sinLambda/sinSigma);var cosSqAlpha=Math.cos(alpha)*Math.cos(alpha);var cos2SigmaM=cosSigma-2*sinU1*sinU2/cosSqAlpha;var C=f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));lambdaP=lambda;lambda=L+(1-C)*f*Math.sin(alpha)*(sigma+C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));}
+if(iterLimit==0){return NaN;}
+var uSq=cosSqAlpha*(a*a-b*b)/(b*b);var A=1+uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));var B=uSq/1024*(256+uSq*(-128+uSq*(74-47*uSq)));var deltaSigma=B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
+B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));var s=b*A*(sigma-deltaSigma);var d=s.toFixed(3)/1000;return d;};OpenLayers.Util.destinationVincenty=function(lonlat,brng,dist){var u=OpenLayers.Util;var ct=u.VincentyConstants;var a=ct.a,b=ct.b,f=ct.f;var lon1=lonlat.lon;var lat1=lonlat.lat;var s=dist;var alpha1=u.rad(brng);var sinAlpha1=Math.sin(alpha1);var cosAlpha1=Math.cos(alpha1);var tanU1=(1-f)*Math.tan(u.rad(lat1));var cosU1=1/Math.sqrt((1+tanU1*tanU1)),sinU1=tanU1*cosU1;var sigma1=Math.atan2(tanU1,cosAlpha1);var sinAlpha=cosU1*sinAlpha1;var cosSqAlpha=1-sinAlpha*sinAlpha;var uSq=cosSqAlpha*(a*a-b*b)/(b*b);var A=1+uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));var B=uSq/1024*(256+uSq*(-128+uSq*(74-47*uSq)));var sigma=s/(b*A),sigmaP=2*Math.PI;while(Math.abs(sigma-sigmaP)>1e-12){var cos2SigmaM=Math.cos(2*sigma1+sigma);var sinSigma=Math.sin(sigma);var cosSigma=Math.cos(sigma);var deltaSigma=B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
+B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));sigmaP=sigma;sigma=s/(b*A)+deltaSigma;}
+var tmp=sinU1*sinSigma-cosU1*cosSigma*cosAlpha1;var lat2=Math.atan2(sinU1*cosSigma+cosU1*sinSigma*cosAlpha1,(1-f)*Math.sqrt(sinAlpha*sinAlpha+tmp*tmp));var lambda=Math.atan2(sinSigma*sinAlpha1,cosU1*cosSigma-sinU1*sinSigma*cosAlpha1);var C=f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));var L=lambda-(1-C)*f*sinAlpha*(sigma+C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));var revAz=Math.atan2(sinAlpha,-tmp);return new OpenLayers.LonLat(lon1+u.deg(L),u.deg(lat2));};OpenLayers.Util.getParameters=function(url){url=(url===null||url===undefined)?window.location.href:url;var paramsString="";if(OpenLayers.String.contains(url,'?')){var start=url.indexOf('?')+1;var end=OpenLayers.String.contains(url,"#")?url.indexOf('#'):url.length;paramsString=url.substring(start,end);}
+var parameters={};var pairs=paramsString.split(/[&;]/);for(var i=0,len=pairs.length;i<len;++i){var keyValue=pairs[i].split('=');if(keyValue[0]){var key=keyValue[0];try{key=decodeURIComponent(key);}catch(err){key=unescape(key);}
+var value=(keyValue[1]||'').replace(/\+/g," ");try{value=decodeURIComponent(value);}catch(err){value=unescape(value);}
+value=value.split(",");if(value.length==1){value=value[0];}
+parameters[key]=value;}}
+return parameters;};OpenLayers.Util.lastSeqID=0;OpenLayers.Util.createUniqueID=function(prefix){if(prefix==null){prefix="id_";}
+OpenLayers.Util.lastSeqID+=1;return prefix+OpenLayers.Util.lastSeqID;};OpenLayers.INCHES_PER_UNIT={'inches':1.0,'ft':12.0,'mi':63360.0,'m':39.3701,'km':39370.1,'dd':4374754,'yd':36};OpenLayers.INCHES_PER_UNIT["in"]=OpenLayers.INCHES_PER_UNIT.inches;OpenLayers.INCHES_PER_UNIT["degrees"]=OpenLayers.INCHES_PER_UNIT.dd;OpenLayers.INCHES_PER_UNIT["nmi"]=1852*OpenLayers.INCHES_PER_UNIT.m;OpenLayers.METERS_PER_INCH=0.02540005080010160020;OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT,{"Inch":OpenLayers.INCHES_PER_UNIT.inches,"Meter":1.0/OpenLayers.METERS_PER_INCH,"Foot":0.30480060960121920243/OpenLayers.METERS_PER_INCH,"IFoot":0.30480000000000000000/OpenLayers.METERS_PER_INCH,"ClarkeFoot":0.3047972651151/OpenLayers.METERS_PER_INCH,"SearsFoot":0.30479947153867624624/OpenLayers.METERS_PER_INCH,"GoldCoastFoot":0.30479971018150881758/OpenLayers.METERS_PER_INCH,"IInch":0.02540000000000000000/OpenLayers.METERS_PER_INCH,"MicroInch":0.00002540000000000000/OpenLayers.METERS_PER_INCH,"Mil":0.00000002540000000000/OpenLayers.METERS_PER_INCH,"Centimeter":0.01000000000000000000/OpenLayers.METERS_PER_INCH,"Kilometer":1000.00000000000000000000/OpenLayers.METERS_PER_INCH,"Yard":0.91440182880365760731/OpenLayers.METERS_PER_INCH,"SearsYard":0.914398414616029/OpenLayers.METERS_PER_INCH,"IndianYard":0.91439853074444079983/OpenLayers.METERS_PER_INCH,"IndianYd37":0.91439523/OpenLayers.METERS_PER_INCH,"IndianYd62":0.9143988/OpenLayers.METERS_PER_INCH,"IndianYd75":0.9143985/OpenLayers.METERS_PER_INCH,"IndianFoot":0.30479951/OpenLayers.METERS_PER_INCH,"IndianFt37":0.30479841/OpenLayers.METERS_PER_INCH,"IndianFt62":0.3047996/OpenLayers.METERS_PER_INCH,"IndianFt75":0.3047995/OpenLayers.METERS_PER_INCH,"Mile":1609.34721869443738887477/OpenLayers.METERS_PER_INCH,"IYard":0.91440000000000000000/OpenLayers.METERS_PER_INCH,"IMile":1609.34400000000000000000/OpenLayers.METERS_PER_INCH,"NautM":1852.00000000000000000000/OpenLayers.METERS_PER_INCH,"Lat-66":110943.316488932731/OpenLayers.METERS_PER_INCH,"Lat-83":110946.25736872234125/OpenLayers.METERS_PER_INCH,"Decimeter":0.10000000000000000000/OpenLayers.METERS_PER_INCH,"Millimeter":0.00100000000000000000/OpenLayers.METERS_PER_INCH,"Dekameter":10.00000000000000000000/OpenLayers.METERS_PER_INCH,"Decameter":10.00000000000000000000/OpenLayers.METERS_PER_INCH,"Hectometer":100.00000000000000000000/OpenLayers.METERS_PER_INCH,"GermanMeter":1.0000135965/OpenLayers.METERS_PER_INCH,"CaGrid":0.999738/OpenLayers.METERS_PER_INCH,"ClarkeChain":20.1166194976/OpenLayers.METERS_PER_INCH,"GunterChain":20.11684023368047/OpenLayers.METERS_PER_INCH,"BenoitChain":20.116782494375872/OpenLayers.METERS_PER_INCH,"SearsChain":20.11676512155/OpenLayers.METERS_PER_INCH,"ClarkeLink":0.201166194976/OpenLayers.METERS_PER_INCH,"GunterLink":0.2011684023368047/OpenLayers.METERS_PER_INCH,"BenoitLink":0.20116782494375872/OpenLayers.METERS_PER_INCH,"SearsLink":0.2011676512155/OpenLayers.METERS_PER_INCH,"Rod":5.02921005842012/OpenLayers.METERS_PER_INCH,"IntnlChain":20.1168/OpenLayers.METERS_PER_INCH,"IntnlLink":0.201168/OpenLayers.METERS_PER_INCH,"Perch":5.02921005842012/OpenLayers.METERS_PER_INCH,"Pole":5.02921005842012/OpenLayers.METERS_PER_INCH,"Furlong":201.1684023368046/OpenLayers.METERS_PER_INCH,"Rood":3.778266898/OpenLayers.METERS_PER_INCH,"CapeFoot":0.3047972615/OpenLayers.METERS_PER_INCH,"Brealey":375.00000000000000000000/OpenLayers.METERS_PER_INCH,"ModAmFt":0.304812252984505969011938/OpenLayers.METERS_PER_INCH,"Fathom":1.8288/OpenLayers.METERS_PER_INCH,"NautM-UK":1853.184/OpenLayers.METERS_PER_INCH,"50kilometers":50000.0/OpenLayers.METERS_PER_INCH,"150kilometers":150000.0/OpenLayers.METERS_PER_INCH});OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT,{"mm":OpenLayers.INCHES_PER_UNIT["Meter"]/1000.0,"cm":OpenLayers.INCHES_PER_UNIT["Meter"]/100.0,"dm":OpenLayers.INCHES_PER_UNIT["Meter"]*100.0,"km":OpenLayers.INCHES_PER_UNIT["Meter"]*1000.0,"kmi":OpenLayers.INCHES_PER_UNIT["nmi"],"fath":OpenLayers.INCHES_PER_UNIT["Fathom"],"ch":OpenLayers.INCHES_PER_UNIT["IntnlChain"],"link":OpenLayers.INCHES_PER_UNIT["IntnlLink"],"us-in":OpenLayers.INCHES_PER_UNIT["inches"],"us-ft":OpenLayers.INCHES_PER_UNIT["Foot"],"us-yd":OpenLayers.INCHES_PER_UNIT["Yard"],"us-ch":OpenLayers.INCHES_PER_UNIT["GunterChain"],"us-mi":OpenLayers.INCHES_PER_UNIT["Mile"],"ind-yd":OpenLayers.INCHES_PER_UNIT["IndianYd37"],"ind-ft":OpenLayers.INCHES_PER_UNIT["IndianFt37"],"ind-ch":20.11669506/OpenLayers.METERS_PER_INCH});OpenLayers.DOTS_PER_INCH=72;OpenLayers.Util.normalizeScale=function(scale){var normScale=(scale>1.0)?(1.0/scale):scale;return normScale;};OpenLayers.Util.getResolutionFromScale=function(scale,units){var resolution;if(scale){if(units==null){units="degrees";}
+var normScale=OpenLayers.Util.normalizeScale(scale);resolution=1/(normScale*OpenLayers.INCHES_PER_UNIT[units]*OpenLayers.DOTS_PER_INCH);}
+return resolution;};OpenLayers.Util.getScaleFromResolution=function(resolution,units){if(units==null){units="degrees";}
+var scale=resolution*OpenLayers.INCHES_PER_UNIT[units]*OpenLayers.DOTS_PER_INCH;return scale;};OpenLayers.Util.pagePosition=function(forElement){var pos=[0,0];var viewportElement=OpenLayers.Util.getViewportElement();if(!forElement||forElement==window||forElement==viewportElement){return pos;}
+var BUGGY_GECKO_BOX_OBJECT=OpenLayers.IS_GECKO&&document.getBoxObjectFor&&OpenLayers.Element.getStyle(forElement,'position')=='absolute'&&(forElement.style.top==''||forElement.style.left=='');var parent=null;var box;if(forElement.getBoundingClientRect){box=forElement.getBoundingClientRect();var scrollTop=viewportElement.scrollTop;var scrollLeft=viewportElement.scrollLeft;pos[0]=box.left+scrollLeft;pos[1]=box.top+scrollTop;}else if(document.getBoxObjectFor&&!BUGGY_GECKO_BOX_OBJECT){box=document.getBoxObjectFor(forElement);var vpBox=document.getBoxObjectFor(viewportElement);pos[0]=box.screenX-vpBox.screenX;pos[1]=box.screenY-vpBox.screenY;}else{pos[0]=forElement.offsetLeft;pos[1]=forElement.offsetTop;parent=forElement.offsetParent;if(parent!=forElement){while(parent){pos[0]+=parent.offsetLeft;pos[1]+=parent.offsetTop;parent=parent.offsetParent;}}
+var browser=OpenLayers.BROWSER_NAME;if(browser=="opera"||(browser=="safari"&&OpenLayers.Element.getStyle(forElement,'position')=='absolute')){pos[1]-=document.body.offsetTop;}
+parent=forElement.offsetParent;while(parent&&parent!=document.body){pos[0]-=parent.scrollLeft;if(browser!="opera"||parent.tagName!='TR'){pos[1]-=parent.scrollTop;}
+parent=parent.offsetParent;}}
+return pos;};OpenLayers.Util.getViewportElement=function(){var viewportElement=arguments.callee.viewportElement;if(viewportElement==undefined){viewportElement=(OpenLayers.BROWSER_NAME=="msie"&&document.compatMode!='CSS1Compat')?document.body:document.documentElement;arguments.callee.viewportElement=viewportElement;}
+return viewportElement;};OpenLayers.Util.isEquivalentUrl=function(url1,url2,options){options=options||{};OpenLayers.Util.applyDefaults(options,{ignoreCase:true,ignorePort80:true,ignoreHash:true});var urlObj1=OpenLayers.Util.createUrlObject(url1,options);var urlObj2=OpenLayers.Util.createUrlObject(url2,options);for(var key in urlObj1){if(key!=="args"){if(urlObj1[key]!=urlObj2[key]){return false;}}}
+for(var key in urlObj1.args){if(urlObj1.args[key]!=urlObj2.args[key]){return false;}
+delete urlObj2.args[key];}
+for(var key in urlObj2.args){return false;}
+return true;};OpenLayers.Util.createUrlObject=function(url,options){options=options||{};if(!(/^\w+:\/\//).test(url)){var loc=window.location;var port=loc.port?":"+loc.port:"";var fullUrl=loc.protocol+"//"+loc.host.split(":").shift()+port;if(url.indexOf("/")===0){url=fullUrl+url;}else{var parts=loc.pathname.split("/");parts.pop();url=fullUrl+parts.join("/")+"/"+url;}}
+if(options.ignoreCase){url=url.toLowerCase();}
+var a=document.createElement('a');a.href=url;var urlObject={};urlObject.host=a.host.split(":").shift();urlObject.protocol=a.protocol;if(options.ignorePort80){urlObject.port=(a.port=="80"||a.port=="0")?"":a.port;}else{urlObject.port=(a.port==""||a.port=="0")?"80":a.port;}
+urlObject.hash=(options.ignoreHash||a.hash==="#")?"":a.hash;var queryString=a.search;if(!queryString){var qMark=url.indexOf("?");queryString=(qMark!=-1)?url.substr(qMark):"";}
+urlObject.args=OpenLayers.Util.getParameters(queryString);urlObject.pathname=(a.pathname.charAt(0)=="/")?a.pathname:"/"+a.pathname;return urlObject;};OpenLayers.Util.removeTail=function(url){var head=null;var qMark=url.indexOf("?");var hashMark=url.indexOf("#");if(qMark==-1){head=(hashMark!=-1)?url.substr(0,hashMark):url;}else{head=(hashMark!=-1)?url.substr(0,Math.min(qMark,hashMark)):url.substr(0,qMark);}
+return head;};OpenLayers.IS_GECKO=(function(){var ua=navigator.userAgent.toLowerCase();return ua.indexOf("webkit")==-1&&ua.indexOf("gecko")!=-1;})();OpenLayers.CANVAS_SUPPORTED=(function(){var elem=document.createElement('canvas');return!!(elem.getContext&&elem.getContext('2d'));})();OpenLayers.BROWSER_NAME=(function(){var name="";var ua=navigator.userAgent.toLowerCase();if(ua.indexOf("opera")!=-1){name="opera";}else if(ua.indexOf("msie")!=-1){name="msie";}else if(ua.indexOf("safari")!=-1){name="safari";}else if(ua.indexOf("mozilla")!=-1){if(ua.indexOf("firefox")!=-1){name="firefox";}else{name="mozilla";}}
+return name;})();OpenLayers.Util.getBrowserName=function(){return OpenLayers.BROWSER_NAME;};OpenLayers.Util.getRenderedDimensions=function(contentHTML,size,options){var w,h;var container=document.createElement("div");container.style.visibility="hidden";var containerElement=(options&&options.containerElement)?options.containerElement:document.body;var parentHasPositionAbsolute=false;var superContainer=null;var parent=containerElement;while(parent&&parent.tagName.toLowerCase()!="body"){var parentPosition=OpenLayers.Element.getStyle(parent,"position");if(parentPosition=="absolute"){parentHasPositionAbsolute=true;break;}else if(parentPosition&&parentPosition!="static"){break;}
+parent=parent.parentNode;}
+if(parentHasPositionAbsolute&&(containerElement.clientHeight===0||containerElement.clientWidth===0)){superContainer=document.createElement("div");superContainer.style.visibility="hidden";superContainer.style.position="absolute";superContainer.style.overflow="visible";superContainer.style.width=document.body.clientWidth+"px";superContainer.style.height=document.body.clientHeight+"px";superContainer.appendChild(container);}
+container.style.position="absolute";if(size){if(size.w){w=size.w;container.style.width=w+"px";}else if(size.h){h=size.h;container.style.height=h+"px";}}
+if(options&&options.displayClass){container.className=options.displayClass;}
+var content=document.createElement("div");content.innerHTML=contentHTML;content.style.overflow="visible";if(content.childNodes){for(var i=0,l=content.childNodes.length;i<l;i++){if(!content.childNodes[i].style)continue;content.childNodes[i].style.overflow="visible";}}
+container.appendChild(content);if(superContainer){containerElement.appendChild(superContainer);}else{containerElement.appendChild(container);}
+if(!w){w=parseInt(content.scrollWidth);container.style.width=w+"px";}
+if(!h){h=parseInt(content.scrollHeight);}
+container.removeChild(content);if(superContainer){superContainer.removeChild(container);containerElement.removeChild(superContainer);}else{containerElement.removeChild(container);}
+return new OpenLayers.Size(w,h);};OpenLayers.Util.getScrollbarWidth=function(){var scrollbarWidth=OpenLayers.Util._scrollbarWidth;if(scrollbarWidth==null){var scr=null;var inn=null;var wNoScroll=0;var wScroll=0;scr=document.createElement('div');scr.style.position='absolute';scr.style.top='-1000px';scr.style.left='-1000px';scr.style.width='100px';scr.style.height='50px';scr.style.overflow='hidden';inn=document.createElement('div');inn.style.width='100%';inn.style.height='200px';scr.appendChild(inn);document.body.appendChild(scr);wNoScroll=inn.offsetWidth;scr.style.overflow='scroll';wScroll=inn.offsetWidth;document.body.removeChild(document.body.lastChild);OpenLayers.Util._scrollbarWidth=(wNoScroll-wScroll);scrollbarWidth=OpenLayers.Util._scrollbarWidth;}
+return scrollbarWidth;};OpenLayers.Util.getFormattedLonLat=function(coordinate,axis,dmsOption){if(!dmsOption){dmsOption='dms';}
+coordinate=(coordinate+540)%360-180;var abscoordinate=Math.abs(coordinate);var coordinatedegrees=Math.floor(abscoordinate);var coordinateminutes=(abscoordinate-coordinatedegrees)/(1/60);var tempcoordinateminutes=coordinateminutes;coordinateminutes=Math.floor(coordinateminutes);var coordinateseconds=(tempcoordinateminutes-coordinateminutes)/(1/60);coordinateseconds=Math.round(coordinateseconds*10);coordinateseconds/=10;if(coordinateseconds>=60){coordinateseconds-=60;coordinateminutes+=1;if(coordinateminutes>=60){coordinateminutes-=60;coordinatedegrees+=1;}}
+if(coordinatedegrees<10){coordinatedegrees="0"+coordinatedegrees;}
+var str=coordinatedegrees+"\u00B0";if(dmsOption.indexOf('dm')>=0){if(coordinateminutes<10){coordinateminutes="0"+coordinateminutes;}
+str+=coordinateminutes+"'";if(dmsOption.indexOf('dms')>=0){if(coordinateseconds<10){coordinateseconds="0"+coordinateseconds;}
+str+=coordinateseconds+'"';}}
+if(axis=="lon"){str+=coordinate<0?OpenLayers.i18n("W"):OpenLayers.i18n("E");}else{str+=coordinate<0?OpenLayers.i18n("S"):OpenLayers.i18n("N");}
+return str;};OpenLayers.Event={observers:false,KEY_SPACE:32,KEY_BACKSPACE:8,KEY_TAB:9,KEY_RETURN:13,KEY_ESC:27,KEY_LEFT:37,KEY_UP:38,KEY_RIGHT:39,KEY_DOWN:40,KEY_DELETE:46,element:function(event){return event.target||event.srcElement;},isSingleTouch:function(event){return event.touches&&event.touches.length==1;},isMultiTouch:function(event){return event.touches&&event.touches.length>1;},isLeftClick:function(event){return(((event.which)&&(event.which==1))||((event.button)&&(event.button==1)));},isRightClick:function(event){return(((event.which)&&(event.which==3))||((event.button)&&(event.button==2)));},stop:function(event,allowDefault){if(!allowDefault){if(event.preventDefault){event.preventDefault();}else{event.returnValue=false;}}
+if(event.stopPropagation){event.stopPropagation();}else{event.cancelBubble=true;}},findElement:function(event,tagName){var element=OpenLayers.Event.element(event);while(element.parentNode&&(!element.tagName||(element.tagName.toUpperCase()!=tagName.toUpperCase()))){element=element.parentNode;}
+return element;},observe:function(elementParam,name,observer,useCapture){var element=OpenLayers.Util.getElement(elementParam);useCapture=useCapture||false;if(name=='keypress'&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.attachEvent)){name='keydown';}
+if(!this.observers){this.observers={};}
+if(!element._eventCacheID){var idPrefix="eventCacheID_";if(element.id){idPrefix=element.id+"_"+idPrefix;}
+element._eventCacheID=OpenLayers.Util.createUniqueID(idPrefix);}
+var cacheID=element._eventCacheID;if(!this.observers[cacheID]){this.observers[cacheID]=[];}
+this.observers[cacheID].push({'element':element,'name':name,'observer':observer,'useCapture':useCapture});if(element.addEventListener){element.addEventListener(name,observer,useCapture);}else if(element.attachEvent){element.attachEvent('on'+name,observer);}},stopObservingElement:function(elementParam){var element=OpenLayers.Util.getElement(elementParam);var cacheID=element._eventCacheID;this._removeElementObservers(OpenLayers.Event.observers[cacheID]);},_removeElementObservers:function(elementObservers){if(elementObservers){for(var i=elementObservers.length-1;i>=0;i--){var entry=elementObservers[i];var args=new Array(entry.element,entry.name,entry.observer,entry.useCapture);var removed=OpenLayers.Event.stopObserving.apply(this,args);}}},stopObserving:function(elementParam,name,observer,useCapture){useCapture=useCapture||false;var element=OpenLayers.Util.getElement(elementParam);var cacheID=element._eventCacheID;if(name=='keypress'){if(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.detachEvent){name='keydown';}}
+var foundEntry=false;var elementObservers=OpenLayers.Event.observers[cacheID];if(elementObservers){var i=0;while(!foundEntry&&i<elementObservers.length){var cacheEntry=elementObservers[i];if((cacheEntry.name==name)&&(cacheEntry.observer==observer)&&(cacheEntry.useCapture==useCapture)){elementObservers.splice(i,1);if(elementObservers.length==0){delete OpenLayers.Event.observers[cacheID];}
+foundEntry=true;break;}
+i++;}}
+if(foundEntry){if(element.removeEventListener){element.removeEventListener(name,observer,useCapture);}else if(element&&element.detachEvent){element.detachEvent('on'+name,observer);}}
+return foundEntry;},unloadCache:function(){if(OpenLayers.Event&&OpenLayers.Event.observers){for(var cacheID in OpenLayers.Event.observers){var elementObservers=OpenLayers.Event.observers[cacheID];OpenLayers.Event._removeElementObservers.apply(this,[elementObservers]);}
+OpenLayers.Event.observers=false;}},CLASS_NAME:"OpenLayers.Event"};OpenLayers.Event.observe(window,'unload',OpenLayers.Event.unloadCache,false);OpenLayers.Events=OpenLayers.Class({BROWSER_EVENTS:["mouseover","mouseout","mousedown","mouseup","mousemove","click","dblclick","rightclick","dblrightclick","resize","focus","blur","touchstart","touchmove","touchend","keydown"],listeners:null,object:null,element:null,eventHandler:null,fallThrough:null,includeXY:false,extensions:null,extensionCount:null,clearMouseListener:null,initialize:function(object,element,eventTypes,fallThrough,options){OpenLayers.Util.extend(this,options);this.object=object;this.fallThrough=fallThrough;this.listeners={};this.extensions={};this.extensionCount={};if(element!=null){this.attachToElement(element);}},destroy:function(){for(var e in this.extensions){if(typeof this.extensions[e]!=="boolean"){this.extensions[e].destroy();}}
+this.extensions=null;if(this.element){OpenLayers.Event.stopObservingElement(this.element);if(this.element.hasScrollEvent){OpenLayers.Event.stopObserving(window,"scroll",this.clearMouseListener);}}
+this.element=null;this.listeners=null;this.object=null;this.fallThrough=null;this.eventHandler=null;},addEventType:function(eventName){},attachToElement:function(element){if(this.element){OpenLayers.Event.stopObservingElement(this.element);}else{this.eventHandler=OpenLayers.Function.bindAsEventListener(this.handleBrowserEvent,this);this.clearMouseListener=OpenLayers.Function.bind(this.clearMouseCache,this);}
+this.element=element;for(var i=0,len=this.BROWSER_EVENTS.length;i<len;i++){OpenLayers.Event.observe(element,this.BROWSER_EVENTS[i],this.eventHandler);}
+OpenLayers.Event.observe(element,"dragstart",OpenLayers.Event.stop);},on:function(object){for(var type in object){if(type!="scope"&&object.hasOwnProperty(type)){this.register(type,object.scope,object[type]);}}},register:function(type,obj,func,priority){if(type in OpenLayers.Events&&!this.extensions[type]){this.extensions[type]=new OpenLayers.Events[type](this);}
+if(func!=null){if(obj==null){obj=this.object;}
+var listeners=this.listeners[type];if(!listeners){listeners=[];this.listeners[type]=listeners;this.extensionCount[type]=0;}
+var listener={obj:obj,func:func};if(priority){listeners.splice(this.extensionCount[type],0,listener);if(typeof priority==="object"&&priority.extension){this.extensionCount[type]++;}}else{listeners.push(listener);}}},registerPriority:function(type,obj,func){this.register(type,obj,func,true);},un:function(object){for(var type in object){if(type!="scope"&&object.hasOwnProperty(type)){this.unregister(type,object.scope,object[type]);}}},unregister:function(type,obj,func){if(obj==null){obj=this.object;}
+var listeners=this.listeners[type];if(listeners!=null){for(var i=0,len=listeners.length;i<len;i++){if(listeners[i].obj==obj&&listeners[i].func==func){listeners.splice(i,1);break;}}}},remove:function(type){if(this.listeners[type]!=null){this.listeners[type]=[];}},triggerEvent:function(type,evt){var listeners=this.listeners[type];if(!listeners||listeners.length==0){return undefined;}
+if(evt==null){evt={};}
+evt.object=this.object;evt.element=this.element;if(!evt.type){evt.type=type;}
+listeners=listeners.slice();var continueChain;for(var i=0,len=listeners.length;i<len;i++){var callback=listeners[i];continueChain=callback.func.apply(callback.obj,[evt]);if((continueChain!=undefined)&&(continueChain==false)){break;}}
+if(!this.fallThrough){OpenLayers.Event.stop(evt,true);}
+return continueChain;},handleBrowserEvent:function(evt){var type=evt.type,listeners=this.listeners[type];if(!listeners||listeners.length==0){return;}
+var touches=evt.touches;if(touches&&touches[0]){var x=0;var y=0;var num=touches.length;var touch;for(var i=0;i<num;++i){touch=touches[i];x+=touch.clientX;y+=touch.clientY;}
+evt.clientX=x/num;evt.clientY=y/num;}
+if(this.includeXY){evt.xy=this.getMousePosition(evt);}
+this.triggerEvent(type,evt);},clearMouseCache:function(){this.element.scrolls=null;this.element.lefttop=null;var body=document.body;if(body&&!((body.scrollTop!=0||body.scrollLeft!=0)&&navigator.userAgent.match(/iPhone/i))){this.element.offsets=null;}},getMousePosition:function(evt){if(!this.includeXY){this.clearMouseCache();}else if(!this.element.hasScrollEvent){OpenLayers.Event.observe(window,"scroll",this.clearMouseListener);this.element.hasScrollEvent=true;}
+if(!this.element.scrolls){var viewportElement=OpenLayers.Util.getViewportElement();this.element.scrolls=[viewportElement.scrollLeft,viewportElement.scrollTop];}
+if(!this.element.lefttop){this.element.lefttop=[(document.documentElement.clientLeft||0),(document.documentElement.clientTop||0)];}
+if(!this.element.offsets){this.element.offsets=OpenLayers.Util.pagePosition(this.element);}
+return new OpenLayers.Pixel((evt.clientX+this.element.scrolls[0])-this.element.offsets[0]
+-this.element.lefttop[0],(evt.clientY+this.element.scrolls[1])-this.element.offsets[1]
+-this.element.lefttop[1]);},CLASS_NAME:"OpenLayers.Events"});OpenLayers.Events.buttonclick=OpenLayers.Class({target:null,events:['mousedown','mouseup','click','dblclick','touchstart','touchmove','touchend','keydown'],startRegEx:/^mousedown|touchstart$/,cancelRegEx:/^touchmove$/,completeRegEx:/^mouseup|touchend$/,initialize:function(target){this.target=target;for(var i=this.events.length-1;i>=0;--i){this.target.register(this.events[i],this,this.buttonClick,{extension:true});}},destroy:function(){for(var i=this.events.length-1;i>=0;--i){this.target.unregister(this.events[i],this,this.buttonClick);}
+delete this.target;},getPressedButton:function(element){var depth=3,button;do{if(OpenLayers.Element.hasClass(element,"olButton")){button=element;break;}
+element=element.parentNode;}while(--depth>0&&element);return button;},buttonClick:function(evt){var propagate=true,element=OpenLayers.Event.element(evt);if(element&&(OpenLayers.Event.isLeftClick(evt)||!~evt.type.indexOf("mouse"))){var button=this.getPressedButton(element);if(button){if(evt.type==="keydown"){switch(evt.keyCode){case OpenLayers.Event.KEY_RETURN:case OpenLayers.Event.KEY_SPACE:this.target.triggerEvent("buttonclick",{buttonElement:button});OpenLayers.Event.stop(evt);propagate=false;break;}}else if(this.startEvt){if(this.completeRegEx.test(evt.type)){var pos=OpenLayers.Util.pagePosition(button);this.target.triggerEvent("buttonclick",{buttonElement:button,buttonXY:{x:this.startEvt.clientX-pos[0],y:this.startEvt.clientY-pos[1]}});}
+if(this.cancelRegEx.test(evt.type)){delete this.startEvt;}
+OpenLayers.Event.stop(evt);propagate=false;}
+if(this.startRegEx.test(evt.type)){this.startEvt=evt;OpenLayers.Event.stop(evt);propagate=false;}}else{delete this.startEvt;}}
+return propagate;}});OpenLayers.Lang["is"]=OpenLayers.Util.applyDefaults({'Permalink':"Varanlegur tengill",'Overlays':"Þekjur",'Base Layer':"Grunnlag",'Scale = 1 : ${scaleDenom}':"Skali = 1 : ${scaleDenom}",'methodDeprecated':"Þetta fall hefur verið úrelt og verður fjarlægt í 3.0. Notaðu ${newMethod} í staðin."});OpenLayers.Geometry=OpenLayers.Class({id:null,parent:null,bounds:null,initialize:function(){this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){this.id=null;this.bounds=null;},clone:function(){return new OpenLayers.Geometry();},setBounds:function(bounds){if(bounds){this.bounds=bounds.clone();}},clearBounds:function(){this.bounds=null;if(this.parent){this.parent.clearBounds();}},extendBounds:function(newBounds){var bounds=this.getBounds();if(!bounds){this.setBounds(newBounds);}else{this.bounds.extend(newBounds);}},getBounds:function(){if(this.bounds==null){this.calculateBounds();}
+return this.bounds;},calculateBounds:function(){},distanceTo:function(geometry,options){},getVertices:function(nodes){},atPoint:function(lonlat,toleranceLon,toleranceLat){var atPoint=false;var bounds=this.getBounds();if((bounds!=null)&&(lonlat!=null)){var dX=(toleranceLon!=null)?toleranceLon:0;var dY=(toleranceLat!=null)?toleranceLat:0;var toleranceBounds=new OpenLayers.Bounds(this.bounds.left-dX,this.bounds.bottom-dY,this.bounds.right+dX,this.bounds.top+dY);atPoint=toleranceBounds.containsLonLat(lonlat);}
+return atPoint;},getLength:function(){return 0.0;},getArea:function(){return 0.0;},getCentroid:function(){return null;},toString:function(){var string;if(OpenLayers.Format&&OpenLayers.Format.WKT){string=OpenLayers.Format.WKT.prototype.write(new OpenLayers.Feature.Vector(this));}else{string=Object.prototype.toString.call(this);}
+return string;},CLASS_NAME:"OpenLayers.Geometry"});OpenLayers.Geometry.fromWKT=function(wkt){var geom;if(OpenLayers.Format&&OpenLayers.Format.WKT){var format=OpenLayers.Geometry.fromWKT.format;if(!format){format=new OpenLayers.Format.WKT();OpenLayers.Geometry.fromWKT.format=format;}
+var result=format.read(wkt);if(result instanceof OpenLayers.Feature.Vector){geom=result.geometry;}else if(OpenLayers.Util.isArray(result)){var len=result.length;var components=new Array(len);for(var i=0;i<len;++i){components[i]=result[i].geometry;}
+geom=new OpenLayers.Geometry.Collection(components);}}
+return geom;};OpenLayers.Geometry.segmentsIntersect=function(seg1,seg2,options){var point=options&&options.point;var tolerance=options&&options.tolerance;var intersection=false;var x11_21=seg1.x1-seg2.x1;var y11_21=seg1.y1-seg2.y1;var x12_11=seg1.x2-seg1.x1;var y12_11=seg1.y2-seg1.y1;var y22_21=seg2.y2-seg2.y1;var x22_21=seg2.x2-seg2.x1;var d=(y22_21*x12_11)-(x22_21*y12_11);var n1=(x22_21*y11_21)-(y22_21*x11_21);var n2=(x12_11*y11_21)-(y12_11*x11_21);if(d==0){if(n1==0&&n2==0){intersection=true;}}else{var along1=n1/d;var along2=n2/d;if(along1>=0&&along1<=1&&along2>=0&&along2<=1){if(!point){intersection=true;}else{var x=seg1.x1+(along1*x12_11);var y=seg1.y1+(along1*y12_11);intersection=new OpenLayers.Geometry.Point(x,y);}}}
+if(tolerance){var dist;if(intersection){if(point){var segs=[seg1,seg2];var seg,x,y;outer:for(var i=0;i<2;++i){seg=segs[i];for(var j=1;j<3;++j){x=seg["x"+j];y=seg["y"+j];dist=Math.sqrt(Math.pow(x-intersection.x,2)+
+Math.pow(y-intersection.y,2));if(dist<tolerance){intersection.x=x;intersection.y=y;break outer;}}}}}else{var segs=[seg1,seg2];var source,target,x,y,p,result;outer:for(var i=0;i<2;++i){source=segs[i];target=segs[(i+1)%2];for(var j=1;j<3;++j){p={x:source["x"+j],y:source["y"+j]};result=OpenLayers.Geometry.distanceToSegment(p,target);if(result.distance<tolerance){if(point){intersection=new OpenLayers.Geometry.Point(p.x,p.y);}else{intersection=true;}
+break outer;}}}}}
+return intersection;};OpenLayers.Geometry.distanceToSegment=function(point,segment){var x0=point.x;var y0=point.y;var x1=segment.x1;var y1=segment.y1;var x2=segment.x2;var y2=segment.y2;var dx=x2-x1;var dy=y2-y1;var along=((dx*(x0-x1))+(dy*(y0-y1)))/(Math.pow(dx,2)+Math.pow(dy,2));var x,y;if(along<=0.0){x=x1;y=y1;}else if(along>=1.0){x=x2;y=y2;}else{x=x1+along*dx;y=y1+along*dy;}
+return{distance:Math.sqrt(Math.pow(x-x0,2)+Math.pow(y-y0,2)),x:x,y:y};};OpenLayers.Lang["te"]=OpenLayers.Util.applyDefaults({'Permalink':"స్థిరలింకు",'W':"ప",'E':"తూ",'N':"ఉ",'S':"ద"});OpenLayers.Control=OpenLayers.Class({id:null,map:null,div:null,type:null,allowSelection:false,displayClass:"",title:"",autoActivate:false,active:null,handler:null,eventListeners:null,events:null,initialize:function(options){this.displayClass=this.CLASS_NAME.replace("OpenLayers.","ol").replace(/\./g,"");OpenLayers.Util.extend(this,options);this.events=new OpenLayers.Events(this);if(this.eventListeners instanceof Object){this.events.on(this.eventListeners);}
+if(this.id==null){this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");}},destroy:function(){if(this.events){if(this.eventListeners){this.events.un(this.eventListeners);}
+this.events.destroy();this.events=null;}
+this.eventListeners=null;if(this.handler){this.handler.destroy();this.handler=null;}
+if(this.handlers){for(var key in this.handlers){if(this.handlers.hasOwnProperty(key)&&typeof this.handlers[key].destroy=="function"){this.handlers[key].destroy();}}
+this.handlers=null;}
+if(this.map){this.map.removeControl(this);this.map=null;}
+this.div=null;},setMap:function(map){this.map=map;if(this.handler){this.handler.setMap(map);}},draw:function(px){if(this.div==null){this.div=OpenLayers.Util.createDiv(this.id);this.div.className=this.displayClass;if(!this.allowSelection){this.div.className+=" olControlNoSelect";this.div.setAttribute("unselectable","on",0);this.div.onselectstart=OpenLayers.Function.False;}
+if(this.title!=""){this.div.title=this.title;}}
+if(px!=null){this.position=px.clone();}
+this.moveTo(this.position);return this.div;},moveTo:function(px){if((px!=null)&&(this.div!=null)){this.div.style.left=px.x+"px";this.div.style.top=px.y+"px";}},activate:function(){if(this.active){return false;}
+if(this.handler){this.handler.activate();}
+this.active=true;if(this.map){OpenLayers.Element.addClass(this.map.viewPortDiv,this.displayClass.replace(/ /g,"")+"Active");}
+this.events.triggerEvent("activate");return true;},deactivate:function(){if(this.active){if(this.handler){this.handler.deactivate();}
+this.active=false;if(this.map){OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass.replace(/ /g,"")+"Active");}
+this.events.triggerEvent("deactivate");return true;}
+return false;},CLASS_NAME:"OpenLayers.Control"});OpenLayers.Control.TYPE_BUTTON=1;OpenLayers.Control.TYPE_TOGGLE=2;OpenLayers.Control.TYPE_TOOL=3;OpenLayers.Control.PanZoom=OpenLayers.Class(OpenLayers.Control,{slideFactor:50,slideRatio:null,buttons:null,position:null,initialize:function(options){this.position=new OpenLayers.Pixel(OpenLayers.Control.PanZoom.X,OpenLayers.Control.PanZoom.Y);OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){if(this.map){this.map.events.unregister("buttonclick",this,this.onButtonClick);}
+this.removeButtons();this.buttons=null;this.position=null;OpenLayers.Control.prototype.destroy.apply(this,arguments);},setMap:function(map){OpenLayers.Control.prototype.setMap.apply(this,arguments);this.map.events.register("buttonclick",this,this.onButtonClick);},draw:function(px){OpenLayers.Control.prototype.draw.apply(this,arguments);px=this.position;this.buttons=[];var sz={w:18,h:18};var centered=new OpenLayers.Pixel(px.x+sz.w/2,px.y);this._addButton("panup","north-mini.png",centered,sz);px.y=centered.y+sz.h;this._addButton("panleft","west-mini.png",px,sz);this._addButton("panright","east-mini.png",px.add(sz.w,0),sz);this._addButton("pandown","south-mini.png",centered.add(0,sz.h*2),sz);this._addButton("zoomin","zoom-plus-mini.png",centered.add(0,sz.h*3+5),sz);this._addButton("zoomworld","zoom-world-mini.png",centered.add(0,sz.h*4+5),sz);this._addButton("zoomout","zoom-minus-mini.png",centered.add(0,sz.h*5+5),sz);return this.div;},_addButton:function(id,img,xy,sz){var imgLocation=OpenLayers.Util.getImageLocation(img);var btn=OpenLayers.Util.createAlphaImageDiv(this.id+"_"+id,xy,sz,imgLocation,"absolute");btn.style.cursor="pointer";this.div.appendChild(btn);btn.action=id;btn.className="olButton";this.buttons.push(btn);return btn;},_removeButton:function(btn){this.div.removeChild(btn);OpenLayers.Util.removeItem(this.buttons,btn);},removeButtons:function(){for(var i=this.buttons.length-1;i>=0;--i){this._removeButton(this.buttons[i]);}},onButtonClick:function(evt){var btn=evt.buttonElement;switch(btn.action){case"panup":this.map.pan(0,-this.getSlideFactor("h"));break;case"pandown":this.map.pan(0,this.getSlideFactor("h"));break;case"panleft":this.map.pan(-this.getSlideFactor("w"),0);break;case"panright":this.map.pan(this.getSlideFactor("w"),0);break;case"zoomin":this.map.zoomIn();break;case"zoomout":this.map.zoomOut();break;case"zoomworld":this.map.zoomToMaxExtent();break;}},getSlideFactor:function(dim){return this.slideRatio?this.map.getSize()[dim]*this.slideRatio:this.slideFactor;},CLASS_NAME:"OpenLayers.Control.PanZoom"});OpenLayers.Control.PanZoom.X=4;OpenLayers.Control.PanZoom.Y=4;OpenLayers.Control.PanZoomBar=OpenLayers.Class(OpenLayers.Control.PanZoom,{zoomStopWidth:18,zoomStopHeight:11,slider:null,sliderEvents:null,zoombarDiv:null,zoomWorldIcon:false,panIcons:true,forceFixedZoomLevel:false,mouseDragStart:null,deltaY:null,zoomStart:null,destroy:function(){this._removeZoomBar();this.map.events.un({"changebaselayer":this.redraw,scope:this});OpenLayers.Control.PanZoom.prototype.destroy.apply(this,arguments);delete this.mouseDragStart;delete this.zoomStart;},setMap:function(map){OpenLayers.Control.PanZoom.prototype.setMap.apply(this,arguments);this.map.events.register("changebaselayer",this,this.redraw);},redraw:function(){if(this.div!=null){this.removeButtons();this._removeZoomBar();}
+this.draw();},draw:function(px){OpenLayers.Control.prototype.draw.apply(this,arguments);px=this.position.clone();this.buttons=[];var sz={w:18,h:18};if(this.panIcons){var centered=new OpenLayers.Pixel(px.x+sz.w/2,px.y);var wposition=sz.w;if(this.zoomWorldIcon){centered=new OpenLayers.Pixel(px.x+sz.w,px.y);}
+this._addButton("panup","north-mini.png",centered,sz);px.y=centered.y+sz.h;this._addButton("panleft","west-mini.png",px,sz);if(this.zoomWorldIcon){this._addButton("zoomworld","zoom-world-mini.png",px.add(sz.w,0),sz);wposition*=2;}
+this._addButton("panright","east-mini.png",px.add(wposition,0),sz);this._addButton("pandown","south-mini.png",centered.add(0,sz.h*2),sz);this._addButton("zoomin","zoom-plus-mini.png",centered.add(0,sz.h*3+5),sz);centered=this._addZoomBar(centered.add(0,sz.h*4+5));this._addButton("zoomout","zoom-minus-mini.png",centered,sz);}
+else{this._addButton("zoomin","zoom-plus-mini.png",px,sz);centered=this._addZoomBar(px.add(0,sz.h));this._addButton("zoomout","zoom-minus-mini.png",centered,sz);if(this.zoomWorldIcon){centered=centered.add(0,sz.h+3);this._addButton("zoomworld","zoom-world-mini.png",centered,sz);}}
+return this.div;},_addZoomBar:function(centered){var imgLocation=OpenLayers.Util.getImageLocation("slider.png");var id=this.id+"_"+this.map.id;var zoomsToEnd=this.map.getNumZoomLevels()-1-this.map.getZoom();var slider=OpenLayers.Util.createAlphaImageDiv(id,centered.add(-1,zoomsToEnd*this.zoomStopHeight),{w:20,h:9},imgLocation,"absolute");slider.style.cursor="move";this.slider=slider;this.sliderEvents=new OpenLayers.Events(this,slider,null,true,{includeXY:true});this.sliderEvents.on({"touchstart":this.zoomBarDown,"touchmove":this.zoomBarDrag,"touchend":this.zoomBarUp,"mousedown":this.zoomBarDown,"mousemove":this.zoomBarDrag,"mouseup":this.zoomBarUp});var sz={w:this.zoomStopWidth,h:this.zoomStopHeight*this.map.getNumZoomLevels()};var imgLocation=OpenLayers.Util.getImageLocation("zoombar.png");var div=null;if(OpenLayers.Util.alphaHack()){var id=this.id+"_"+this.map.id;div=OpenLayers.Util.createAlphaImageDiv(id,centered,{w:sz.w,h:this.zoomStopHeight},imgLocation,"absolute",null,"crop");div.style.height=sz.h+"px";}else{div=OpenLayers.Util.createDiv('OpenLayers_Control_PanZoomBar_Zoombar'+this.map.id,centered,sz,imgLocation);}
+div.style.cursor="pointer";div.className="olButton";this.zoombarDiv=div;this.div.appendChild(div);this.startTop=parseInt(div.style.top);this.div.appendChild(slider);this.map.events.register("zoomend",this,this.moveZoomBar);centered=centered.add(0,this.zoomStopHeight*this.map.getNumZoomLevels());return centered;},_removeZoomBar:function(){this.sliderEvents.un({"touchstart":this.zoomBarDown,"touchmove":this.zoomBarDrag,"touchend":this.zoomBarUp,"mousedown":this.zoomBarDown,"mousemove":this.zoomBarDrag,"mouseup":this.zoomBarUp});this.sliderEvents.destroy();this.div.removeChild(this.zoombarDiv);this.zoombarDiv=null;this.div.removeChild(this.slider);this.slider=null;this.map.events.unregister("zoomend",this,this.moveZoomBar);},onButtonClick:function(evt){OpenLayers.Control.PanZoom.prototype.onButtonClick.apply(this,arguments);if(evt.buttonElement===this.zoombarDiv){var levels=evt.buttonXY.y/this.zoomStopHeight;if(this.forceFixedZoomLevel||!this.map.fractionalZoom){levels=Math.floor(levels);}
+var zoom=(this.map.getNumZoomLevels()-1)-levels;zoom=Math.min(Math.max(zoom,0),this.map.getNumZoomLevels()-1);this.map.zoomTo(zoom);}},passEventToSlider:function(evt){this.sliderEvents.handleBrowserEvent(evt);},zoomBarDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)&&!OpenLayers.Event.isSingleTouch(evt)){return;}
+this.map.events.on({"touchmove":this.passEventToSlider,"mousemove":this.passEventToSlider,"mouseup":this.passEventToSlider,scope:this});this.mouseDragStart=evt.xy.clone();this.zoomStart=evt.xy.clone();this.div.style.cursor="move";this.zoombarDiv.offsets=null;OpenLayers.Event.stop(evt);},zoomBarDrag:function(evt){if(this.mouseDragStart!=null){var deltaY=this.mouseDragStart.y-evt.xy.y;var offsets=OpenLayers.Util.pagePosition(this.zoombarDiv);if((evt.clientY-offsets[1])>0&&(evt.clientY-offsets[1])<parseInt(this.zoombarDiv.style.height)-2){var newTop=parseInt(this.slider.style.top)-deltaY;this.slider.style.top=newTop+"px";this.mouseDragStart=evt.xy.clone();}
+this.deltaY=this.zoomStart.y-evt.xy.y;OpenLayers.Event.stop(evt);}},zoomBarUp:function(evt){if(!OpenLayers.Event.isLeftClick(evt)&&evt.type!=="touchend"){return;}
+if(this.mouseDragStart){this.div.style.cursor="";this.map.events.un({"touchmove":this.passEventToSlider,"mouseup":this.passEventToSlider,"mousemove":this.passEventToSlider,scope:this});var zoomLevel=this.map.zoom;if(!this.forceFixedZoomLevel&&this.map.fractionalZoom){zoomLevel+=this.deltaY/this.zoomStopHeight;zoomLevel=Math.min(Math.max(zoomLevel,0),this.map.getNumZoomLevels()-1);}else{zoomLevel+=this.deltaY/this.zoomStopHeight;zoomLevel=Math.max(Math.round(zoomLevel),0);}
+this.map.zoomTo(zoomLevel);this.mouseDragStart=null;this.zoomStart=null;this.deltaY=0;OpenLayers.Event.stop(evt);}},moveZoomBar:function(){var newTop=((this.map.getNumZoomLevels()-1)-this.map.getZoom())*this.zoomStopHeight+this.startTop+1;this.slider.style.top=newTop+"px";},CLASS_NAME:"OpenLayers.Control.PanZoomBar"});OpenLayers.Geometry.Collection=OpenLayers.Class(OpenLayers.Geometry,{components:null,componentTypes:null,initialize:function(components){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.components=[];if(components!=null){this.addComponents(components);}},destroy:function(){this.components.length=0;this.components=null;OpenLayers.Geometry.prototype.destroy.apply(this,arguments);},clone:function(){var geometry=eval("new "+this.CLASS_NAME+"()");for(var i=0,len=this.components.length;i<len;i++){geometry.addComponent(this.components[i].clone());}
+OpenLayers.Util.applyDefaults(geometry,this);return geometry;},getComponentsString:function(){var strings=[];for(var i=0,len=this.components.length;i<len;i++){strings.push(this.components[i].toShortString());}
+return strings.join(",");},calculateBounds:function(){this.bounds=null;var bounds=new OpenLayers.Bounds();var components=this.components;if(components){for(var i=0,len=components.length;i<len;i++){bounds.extend(components[i].getBounds());}}
+if(bounds.left!=null&&bounds.bottom!=null&&bounds.right!=null&&bounds.top!=null){this.setBounds(bounds);}},addComponents:function(components){if(!(OpenLayers.Util.isArray(components))){components=[components];}
+for(var i=0,len=components.length;i<len;i++){this.addComponent(components[i]);}},addComponent:function(component,index){var added=false;if(component){if(this.componentTypes==null||(OpenLayers.Util.indexOf(this.componentTypes,component.CLASS_NAME)>-1)){if(index!=null&&(index<this.components.length)){var components1=this.components.slice(0,index);var components2=this.components.slice(index,this.components.length);components1.push(component);this.components=components1.concat(components2);}else{this.components.push(component);}
+component.parent=this;this.clearBounds();added=true;}}
+return added;},removeComponents:function(components){var removed=false;if(!(OpenLayers.Util.isArray(components))){components=[components];}
+for(var i=components.length-1;i>=0;--i){removed=this.removeComponent(components[i])||removed;}
+return removed;},removeComponent:function(component){OpenLayers.Util.removeItem(this.components,component);this.clearBounds();return true;},getLength:function(){var length=0.0;for(var i=0,len=this.components.length;i<len;i++){length+=this.components[i].getLength();}
+return length;},getArea:function(){var area=0.0;for(var i=0,len=this.components.length;i<len;i++){area+=this.components[i].getArea();}
+return area;},getGeodesicArea:function(projection){var area=0.0;for(var i=0,len=this.components.length;i<len;i++){area+=this.components[i].getGeodesicArea(projection);}
+return area;},getCentroid:function(weighted){if(!weighted){return this.components.length&&this.components[0].getCentroid();}
+var len=this.components.length;if(!len){return false;}
+var areas=[];var centroids=[];var areaSum=0;var minArea=Number.MAX_VALUE;var component;for(var i=0;i<len;++i){component=this.components[i];var area=component.getArea();var centroid=component.getCentroid(true);if(isNaN(area)||isNaN(centroid.x)||isNaN(centroid.y)){continue;}
+areas.push(area);areaSum+=area;minArea=(area<minArea&&area>0)?area:minArea;centroids.push(centroid);}
+len=areas.length;if(areaSum===0){for(var i=0;i<len;++i){areas[i]=1;}
+areaSum=areas.length;}else{for(var i=0;i<len;++i){areas[i]/=minArea;}
+areaSum/=minArea;}
+var xSum=0,ySum=0,centroid,area;for(var i=0;i<len;++i){centroid=centroids[i];area=areas[i];xSum+=centroid.x*area;ySum+=centroid.y*area;}
+return new OpenLayers.Geometry.Point(xSum/areaSum,ySum/areaSum);},getGeodesicLength:function(projection){var length=0.0;for(var i=0,len=this.components.length;i<len;i++){length+=this.components[i].getGeodesicLength(projection);}
+return length;},move:function(x,y){for(var i=0,len=this.components.length;i<len;i++){this.components[i].move(x,y);}},rotate:function(angle,origin){for(var i=0,len=this.components.length;i<len;++i){this.components[i].rotate(angle,origin);}},resize:function(scale,origin,ratio){for(var i=0;i<this.components.length;++i){this.components[i].resize(scale,origin,ratio);}
+return this;},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var details=edge&&options&&options.details;var result,best,distance;var min=Number.POSITIVE_INFINITY;for(var i=0,len=this.components.length;i<len;++i){result=this.components[i].distanceTo(geometry,options);distance=details?result.distance:result;if(distance<min){min=distance;best=result;if(min==0){break;}}}
+return best;},equals:function(geometry){var equivalent=true;if(!geometry||!geometry.CLASS_NAME||(this.CLASS_NAME!=geometry.CLASS_NAME)){equivalent=false;}else if(!(OpenLayers.Util.isArray(geometry.components))||(geometry.components.length!=this.components.length)){equivalent=false;}else{for(var i=0,len=this.components.length;i<len;++i){if(!this.components[i].equals(geometry.components[i])){equivalent=false;break;}}}
+return equivalent;},transform:function(source,dest){if(source&&dest){for(var i=0,len=this.components.length;i<len;i++){var component=this.components[i];component.transform(source,dest);}
+this.bounds=null;}
+return this;},intersects:function(geometry){var intersect=false;for(var i=0,len=this.components.length;i<len;++i){intersect=geometry.intersects(this.components[i]);if(intersect){break;}}
+return intersect;},getVertices:function(nodes){var vertices=[];for(var i=0,len=this.components.length;i<len;++i){Array.prototype.push.apply(vertices,this.components[i].getVertices(nodes));}
+return vertices;},CLASS_NAME:"OpenLayers.Geometry.Collection"});OpenLayers.Geometry.Point=OpenLayers.Class(OpenLayers.Geometry,{x:null,y:null,initialize:function(x,y){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.x=parseFloat(x);this.y=parseFloat(y);},clone:function(obj){if(obj==null){obj=new OpenLayers.Geometry.Point(this.x,this.y);}
+OpenLayers.Util.applyDefaults(obj,this);return obj;},calculateBounds:function(){this.bounds=new OpenLayers.Bounds(this.x,this.y,this.x,this.y);},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var details=edge&&options&&options.details;var distance,x0,y0,x1,y1,result;if(geometry instanceof OpenLayers.Geometry.Point){x0=this.x;y0=this.y;x1=geometry.x;y1=geometry.y;distance=Math.sqrt(Math.pow(x0-x1,2)+Math.pow(y0-y1,2));result=!details?distance:{x0:x0,y0:y0,x1:x1,y1:y1,distance:distance};}else{result=geometry.distanceTo(this,options);if(details){result={x0:result.x1,y0:result.y1,x1:result.x0,y1:result.y0,distance:result.distance};}}
+return result;},equals:function(geom){var equals=false;if(geom!=null){equals=((this.x==geom.x&&this.y==geom.y)||(isNaN(this.x)&&isNaN(this.y)&&isNaN(geom.x)&&isNaN(geom.y)));}
+return equals;},toShortString:function(){return(this.x+", "+this.y);},move:function(x,y){this.x=this.x+x;this.y=this.y+y;this.clearBounds();},rotate:function(angle,origin){angle*=Math.PI/180;var radius=this.distanceTo(origin);var theta=angle+Math.atan2(this.y-origin.y,this.x-origin.x);this.x=origin.x+(radius*Math.cos(theta));this.y=origin.y+(radius*Math.sin(theta));this.clearBounds();},getCentroid:function(){return new OpenLayers.Geometry.Point(this.x,this.y);},resize:function(scale,origin,ratio){ratio=(ratio==undefined)?1:ratio;this.x=origin.x+(scale*ratio*(this.x-origin.x));this.y=origin.y+(scale*(this.y-origin.y));this.clearBounds();return this;},intersects:function(geometry){var intersect=false;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){intersect=this.equals(geometry);}else{intersect=geometry.intersects(this);}
+return intersect;},transform:function(source,dest){if((source&&dest)){OpenLayers.Projection.transform(this,source,dest);this.bounds=null;}
+return this;},getVertices:function(nodes){return[this];},CLASS_NAME:"OpenLayers.Geometry.Point"});OpenLayers.Geometry.MultiPoint=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.Point"],addPoint:function(point,index){this.addComponent(point,index);},removePoint:function(point){this.removeComponent(point);},CLASS_NAME:"OpenLayers.Geometry.MultiPoint"});OpenLayers.Geometry.Curve=OpenLayers.Class(OpenLayers.Geometry.MultiPoint,{componentTypes:["OpenLayers.Geometry.Point"],getLength:function(){var length=0.0;if(this.components&&(this.components.length>1)){for(var i=1,len=this.components.length;i<len;i++){length+=this.components[i-1].distanceTo(this.components[i]);}}
+return length;},getGeodesicLength:function(projection){var geom=this;if(projection){var gg=new OpenLayers.Projection("EPSG:4326");if(!gg.equals(projection)){geom=this.clone().transform(projection,gg);}}
+var length=0.0;if(geom.components&&(geom.components.length>1)){var p1,p2;for(var i=1,len=geom.components.length;i<len;i++){p1=geom.components[i-1];p2=geom.components[i];length+=OpenLayers.Util.distVincenty({lon:p1.x,lat:p1.y},{lon:p2.x,lat:p2.y});}}
+return length*1000;},CLASS_NAME:"OpenLayers.Geometry.Curve"});OpenLayers.Geometry.LineString=OpenLayers.Class(OpenLayers.Geometry.Curve,{removeComponent:function(point){var removed=this.components&&(this.components.length>2);if(removed){OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,arguments);}
+return removed;},intersects:function(geometry){var intersect=false;var type=geometry.CLASS_NAME;if(type=="OpenLayers.Geometry.LineString"||type=="OpenLayers.Geometry.LinearRing"||type=="OpenLayers.Geometry.Point"){var segs1=this.getSortedSegments();var segs2;if(type=="OpenLayers.Geometry.Point"){segs2=[{x1:geometry.x,y1:geometry.y,x2:geometry.x,y2:geometry.y}];}else{segs2=geometry.getSortedSegments();}
+var seg1,seg1x1,seg1x2,seg1y1,seg1y2,seg2,seg2y1,seg2y2;outer:for(var i=0,len=segs1.length;i<len;++i){seg1=segs1[i];seg1x1=seg1.x1;seg1x2=seg1.x2;seg1y1=seg1.y1;seg1y2=seg1.y2;inner:for(var j=0,jlen=segs2.length;j<jlen;++j){seg2=segs2[j];if(seg2.x1>seg1x2){break;}
+if(seg2.x2<seg1x1){continue;}
+seg2y1=seg2.y1;seg2y2=seg2.y2;if(Math.min(seg2y1,seg2y2)>Math.max(seg1y1,seg1y2)){continue;}
+if(Math.max(seg2y1,seg2y2)<Math.min(seg1y1,seg1y2)){continue;}
+if(OpenLayers.Geometry.segmentsIntersect(seg1,seg2)){intersect=true;break outer;}}}}else{intersect=geometry.intersects(this);}
+return intersect;},getSortedSegments:function(){var numSeg=this.components.length-1;var segments=new Array(numSeg),point1,point2;for(var i=0;i<numSeg;++i){point1=this.components[i];point2=this.components[i+1];if(point1.x<point2.x){segments[i]={x1:point1.x,y1:point1.y,x2:point2.x,y2:point2.y};}else{segments[i]={x1:point2.x,y1:point2.y,x2:point1.x,y2:point1.y};}}
+function byX1(seg1,seg2){return seg1.x1-seg2.x1;}
+return segments.sort(byX1);},splitWithSegment:function(seg,options){var edge=!(options&&options.edge===false);var tolerance=options&&options.tolerance;var lines=[];var verts=this.getVertices();var points=[];var intersections=[];var split=false;var vert1,vert2,point;var node,vertex,target;var interOptions={point:true,tolerance:tolerance};var result=null;for(var i=0,stop=verts.length-2;i<=stop;++i){vert1=verts[i];points.push(vert1.clone());vert2=verts[i+1];target={x1:vert1.x,y1:vert1.y,x2:vert2.x,y2:vert2.y};point=OpenLayers.Geometry.segmentsIntersect(seg,target,interOptions);if(point instanceof OpenLayers.Geometry.Point){if((point.x===seg.x1&&point.y===seg.y1)||(point.x===seg.x2&&point.y===seg.y2)||point.equals(vert1)||point.equals(vert2)){vertex=true;}else{vertex=false;}
+if(vertex||edge){if(!point.equals(intersections[intersections.length-1])){intersections.push(point.clone());}
+if(i===0){if(point.equals(vert1)){continue;}}
+if(point.equals(vert2)){continue;}
+split=true;if(!point.equals(vert1)){points.push(point);}
+lines.push(new OpenLayers.Geometry.LineString(points));points=[point.clone()];}}}
+if(split){points.push(vert2.clone());lines.push(new OpenLayers.Geometry.LineString(points));}
+if(intersections.length>0){var xDir=seg.x1<seg.x2?1:-1;var yDir=seg.y1<seg.y2?1:-1;result={lines:lines,points:intersections.sort(function(p1,p2){return(xDir*p1.x-xDir*p2.x)||(yDir*p1.y-yDir*p2.y);})};}
+return result;},split:function(target,options){var results=null;var mutual=options&&options.mutual;var sourceSplit,targetSplit,sourceParts,targetParts;if(target instanceof OpenLayers.Geometry.LineString){var verts=this.getVertices();var vert1,vert2,seg,splits,lines,point;var points=[];sourceParts=[];for(var i=0,stop=verts.length-2;i<=stop;++i){vert1=verts[i];vert2=verts[i+1];seg={x1:vert1.x,y1:vert1.y,x2:vert2.x,y2:vert2.y};targetParts=targetParts||[target];if(mutual){points.push(vert1.clone());}
+for(var j=0;j<targetParts.length;++j){splits=targetParts[j].splitWithSegment(seg,options);if(splits){lines=splits.lines;if(lines.length>0){lines.unshift(j,1);Array.prototype.splice.apply(targetParts,lines);j+=lines.length-2;}
+if(mutual){for(var k=0,len=splits.points.length;k<len;++k){point=splits.points[k];if(!point.equals(vert1)){points.push(point);sourceParts.push(new OpenLayers.Geometry.LineString(points));if(point.equals(vert2)){points=[];}else{points=[point.clone()];}}}}}}}
+if(mutual&&sourceParts.length>0&&points.length>0){points.push(vert2.clone());sourceParts.push(new OpenLayers.Geometry.LineString(points));}}else{results=target.splitWith(this,options);}
+if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];}
+if(sourceParts&&sourceParts.length>1){sourceSplit=true;}else{sourceParts=[];}
+if(targetSplit||sourceSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}}
+return results;},splitWith:function(geometry,options){return geometry.split(this,options);},getVertices:function(nodes){var vertices;if(nodes===true){vertices=[this.components[0],this.components[this.components.length-1]];}else if(nodes===false){vertices=this.components.slice(1,this.components.length-1);}else{vertices=this.components.slice();}
+return vertices;},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var details=edge&&options&&options.details;var result,best={};var min=Number.POSITIVE_INFINITY;if(geometry instanceof OpenLayers.Geometry.Point){var segs=this.getSortedSegments();var x=geometry.x;var y=geometry.y;var seg;for(var i=0,len=segs.length;i<len;++i){seg=segs[i];result=OpenLayers.Geometry.distanceToSegment(geometry,seg);if(result.distance<min){min=result.distance;best=result;if(min===0){break;}}else{if(seg.x2>x&&((y>seg.y1&&y<seg.y2)||(y<seg.y1&&y>seg.y2))){break;}}}
+if(details){best={distance:best.distance,x0:best.x,y0:best.y,x1:x,y1:y};}else{best=best.distance;}}else if(geometry instanceof OpenLayers.Geometry.LineString){var segs0=this.getSortedSegments();var segs1=geometry.getSortedSegments();var seg0,seg1,intersection,x0,y0;var len1=segs1.length;var interOptions={point:true};outer:for(var i=0,len=segs0.length;i<len;++i){seg0=segs0[i];x0=seg0.x1;y0=seg0.y1;for(var j=0;j<len1;++j){seg1=segs1[j];intersection=OpenLayers.Geometry.segmentsIntersect(seg0,seg1,interOptions);if(intersection){min=0;best={distance:0,x0:intersection.x,y0:intersection.y,x1:intersection.x,y1:intersection.y};break outer;}else{result=OpenLayers.Geometry.distanceToSegment({x:x0,y:y0},seg1);if(result.distance<min){min=result.distance;best={distance:min,x0:x0,y0:y0,x1:result.x,y1:result.y};}}}}
+if(!details){best=best.distance;}
+if(min!==0){if(seg0){result=geometry.distanceTo(new OpenLayers.Geometry.Point(seg0.x2,seg0.y2),options);var dist=details?result.distance:result;if(dist<min){if(details){best={distance:min,x0:result.x1,y0:result.y1,x1:result.x0,y1:result.y0};}else{best=dist;}}}}}else{best=geometry.distanceTo(this,options);if(details){best={distance:best.distance,x0:best.x1,y0:best.y1,x1:best.x0,y1:best.y0};}}
+return best;},simplify:function(tolerance){if(this&&this!==null){var points=this.getVertices();if(points.length<3){return this;}
+var compareNumbers=function(a,b){return(a-b);};var douglasPeuckerReduction=function(points,firstPoint,lastPoint,tolerance){var maxDistance=0;var indexFarthest=0;for(var index=firstPoint,distance;index<lastPoint;index++){distance=perpendicularDistance(points[firstPoint],points[lastPoint],points[index]);if(distance>maxDistance){maxDistance=distance;indexFarthest=index;}}
+if(maxDistance>tolerance&&indexFarthest!=firstPoint){pointIndexsToKeep.push(indexFarthest);douglasPeuckerReduction(points,firstPoint,indexFarthest,tolerance);douglasPeuckerReduction(points,indexFarthest,lastPoint,tolerance);}};var perpendicularDistance=function(point1,point2,point){var area=Math.abs(0.5*(point1.x*point2.y+point2.x*point.y+point.x*point1.y-point2.x*point1.y-point.x*point2.y-point1.x*point.y));var bottom=Math.sqrt(Math.pow(point1.x-point2.x,2)+Math.pow(point1.y-point2.y,2));var height=area/bottom*2;return height;};var firstPoint=0;var lastPoint=points.length-1;var pointIndexsToKeep=[];pointIndexsToKeep.push(firstPoint);pointIndexsToKeep.push(lastPoint);while(points[firstPoint].equals(points[lastPoint])){lastPoint--;pointIndexsToKeep.push(lastPoint);}
+douglasPeuckerReduction(points,firstPoint,lastPoint,tolerance);var returnPoints=[];pointIndexsToKeep.sort(compareNumbers);for(var index=0;index<pointIndexsToKeep.length;index++){returnPoints.push(points[pointIndexsToKeep[index]]);}
+return new OpenLayers.Geometry.LineString(returnPoints);}
+else{return this;}},CLASS_NAME:"OpenLayers.Geometry.LineString"});OpenLayers.Geometry.LinearRing=OpenLayers.Class(OpenLayers.Geometry.LineString,{componentTypes:["OpenLayers.Geometry.Point"],addComponent:function(point,index){var added=false;var lastPoint=this.components.pop();if(index!=null||!point.equals(lastPoint)){added=OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,arguments);}
+var firstPoint=this.components[0];OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,[firstPoint]);return added;},removeComponent:function(point){var removed=this.components&&(this.components.length>3);if(removed){this.components.pop();OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,arguments);var firstPoint=this.components[0];OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,[firstPoint]);}
+return removed;},move:function(x,y){for(var i=0,len=this.components.length;i<len-1;i++){this.components[i].move(x,y);}},rotate:function(angle,origin){for(var i=0,len=this.components.length;i<len-1;++i){this.components[i].rotate(angle,origin);}},resize:function(scale,origin,ratio){for(var i=0,len=this.components.length;i<len-1;++i){this.components[i].resize(scale,origin,ratio);}
+return this;},transform:function(source,dest){if(source&&dest){for(var i=0,len=this.components.length;i<len-1;i++){var component=this.components[i];component.transform(source,dest);}
+this.bounds=null;}
+return this;},getCentroid:function(){if(this.components&&(this.components.length>2)){var sumX=0.0;var sumY=0.0;for(var i=0;i<this.components.length-1;i++){var b=this.components[i];var c=this.components[i+1];sumX+=(b.x+c.x)*(b.x*c.y-c.x*b.y);sumY+=(b.y+c.y)*(b.x*c.y-c.x*b.y);}
+var area=-1*this.getArea();var x=sumX/(6*area);var y=sumY/(6*area);return new OpenLayers.Geometry.Point(x,y);}else{return null;}},getArea:function(){var area=0.0;if(this.components&&(this.components.length>2)){var sum=0.0;for(var i=0,len=this.components.length;i<len-1;i++){var b=this.components[i];var c=this.components[i+1];sum+=(b.x+c.x)*(c.y-b.y);}
+area=-sum/2.0;}
+return area;},getGeodesicArea:function(projection){var ring=this;if(projection){var gg=new OpenLayers.Projection("EPSG:4326");if(!gg.equals(projection)){ring=this.clone().transform(projection,gg);}}
+var area=0.0;var len=ring.components&&ring.components.length;if(len>2){var p1,p2;for(var i=0;i<len-1;i++){p1=ring.components[i];p2=ring.components[i+1];area+=OpenLayers.Util.rad(p2.x-p1.x)*(2+Math.sin(OpenLayers.Util.rad(p1.y))+
+Math.sin(OpenLayers.Util.rad(p2.y)));}
+area=area*6378137.0*6378137.0/2.0;}
+return area;},containsPoint:function(point){var approx=OpenLayers.Number.limitSigDigs;var digs=14;var px=approx(point.x,digs);var py=approx(point.y,digs);function getX(y,x1,y1,x2,y2){return(y-y2)*((x2-x1)/(y2-y1))+x2;}
+var numSeg=this.components.length-1;var start,end,x1,y1,x2,y2,cx,cy;var crosses=0;for(var i=0;i<numSeg;++i){start=this.components[i];x1=approx(start.x,digs);y1=approx(start.y,digs);end=this.components[i+1];x2=approx(end.x,digs);y2=approx(end.y,digs);if(y1==y2){if(py==y1){if(x1<=x2&&(px>=x1&&px<=x2)||x1>=x2&&(px<=x1&&px>=x2)){crosses=-1;break;}}
+continue;}
+cx=approx(getX(py,x1,y1,x2,y2),digs);if(cx==px){if(y1<y2&&(py>=y1&&py<=y2)||y1>y2&&(py<=y1&&py>=y2)){crosses=-1;break;}}
+if(cx<=px){continue;}
+if(x1!=x2&&(cx<Math.min(x1,x2)||cx>Math.max(x1,x2))){continue;}
+if(y1<y2&&(py>=y1&&py<y2)||y1>y2&&(py<y1&&py>=y2)){++crosses;}}
+var contained=(crosses==-1)?1:!!(crosses&1);return contained;},intersects:function(geometry){var intersect=false;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){intersect=this.containsPoint(geometry);}else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LineString"){intersect=geometry.intersects(this);}else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LinearRing"){intersect=OpenLayers.Geometry.LineString.prototype.intersects.apply(this,[geometry]);}else{for(var i=0,len=geometry.components.length;i<len;++i){intersect=geometry.components[i].intersects(this);if(intersect){break;}}}
+return intersect;},getVertices:function(nodes){return(nodes===true)?[]:this.components.slice(0,this.components.length-1);},CLASS_NAME:"OpenLayers.Geometry.LinearRing"});OpenLayers.Animation=(function(window){var isNative=!!(window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame);var requestFrame=(function(){var request=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(callback,element){window.setTimeout(callback,16);};return function(callback,element){request.apply(window,[callback,element]);};})();var counter=0;var loops={};function start(callback,duration,element){duration=duration>0?duration:Number.POSITIVE_INFINITY;var id=++counter;var start=+new Date;loops[id]=function(){if(loops[id]&&+new Date-start<=duration){callback();if(loops[id]){requestFrame(loops[id],element);}}else{delete loops[id];}};requestFrame(loops[id],element);return id;}
+function stop(id){delete loops[id];}
+return{isNative:isNative,requestFrame:requestFrame,start:start,stop:stop};})(window);OpenLayers.Tween=OpenLayers.Class({easing:null,begin:null,finish:null,duration:null,callbacks:null,time:null,animationId:null,playing:false,initialize:function(easing){this.easing=(easing)?easing:OpenLayers.Easing.Expo.easeOut;},start:function(begin,finish,duration,options){this.playing=true;this.begin=begin;this.finish=finish;this.duration=duration;this.callbacks=options.callbacks;this.time=0;OpenLayers.Animation.stop(this.animationId);this.animationId=null;if(this.callbacks&&this.callbacks.start){this.callbacks.start.call(this,this.begin);}
+this.animationId=OpenLayers.Animation.start(OpenLayers.Function.bind(this.play,this));},stop:function(){if(!this.playing){return;}
+if(this.callbacks&&this.callbacks.done){this.callbacks.done.call(this,this.finish);}
+OpenLayers.Animation.stop(this.animationId);this.animationId=null;this.playing=false;},play:function(){var value={};for(var i in this.begin){var b=this.begin[i];var f=this.finish[i];if(b==null||f==null||isNaN(b)||isNaN(f)){throw new TypeError('invalid value for Tween');}
+var c=f-b;value[i]=this.easing.apply(this,[this.time,b,c,this.duration]);}
+this.time++;if(this.callbacks&&this.callbacks.eachStep){this.callbacks.eachStep.call(this,value);}
+if(this.time>this.duration){this.stop();}},CLASS_NAME:"OpenLayers.Tween"});OpenLayers.Easing={CLASS_NAME:"OpenLayers.Easing"};OpenLayers.Easing.Linear={easeIn:function(t,b,c,d){return c*t/d+b;},easeOut:function(t,b,c,d){return c*t/d+b;},easeInOut:function(t,b,c,d){return c*t/d+b;},CLASS_NAME:"OpenLayers.Easing.Linear"};OpenLayers.Easing.Expo={easeIn:function(t,b,c,d){return(t==0)?b:c*Math.pow(2,10*(t/d-1))+b;},easeOut:function(t,b,c,d){return(t==d)?b+c:c*(-Math.pow(2,-10*t/d)+1)+b;},easeInOut:function(t,b,c,d){if(t==0)return b;if(t==d)return b+c;if((t/=d/2)<1)return c/2*Math.pow(2,10*(t-1))+b;return c/2*(-Math.pow(2,-10*--t)+2)+b;},CLASS_NAME:"OpenLayers.Easing.Expo"};OpenLayers.Easing.Quad={easeIn:function(t,b,c,d){return c*(t/=d)*t+b;},easeOut:function(t,b,c,d){return-c*(t/=d)*(t-2)+b;},easeInOut:function(t,b,c,d){if((t/=d/2)<1)return c/2*t*t+b;return-c/2*((--t)*(t-2)-1)+b;},CLASS_NAME:"OpenLayers.Easing.Quad"};OpenLayers.Projection=OpenLayers.Class({proj:null,projCode:null,titleRegEx:/\+title=[^\+]*/,initialize:function(projCode,options){OpenLayers.Util.extend(this,options);this.projCode=projCode;if(window.Proj4js){this.proj=new Proj4js.Proj(projCode);}},getCode:function(){return this.proj?this.proj.srsCode:this.projCode;},getUnits:function(){return this.proj?this.proj.units:null;},toString:function(){return this.getCode();},equals:function(projection){var p=projection,equals=false;if(p){if(!(p instanceof OpenLayers.Projection)){p=new OpenLayers.Projection(p);}
+if(window.Proj4js&&this.proj.defData&&p.proj.defData){equals=this.proj.defData.replace(this.titleRegEx,"")==p.proj.defData.replace(this.titleRegEx,"");}else if(p.getCode){var source=this.getCode(),target=p.getCode();equals=source==target||!!OpenLayers.Projection.transforms[source]&&OpenLayers.Projection.transforms[source][target]===OpenLayers.Projection.nullTransform;}}
+return equals;},destroy:function(){delete this.proj;delete this.projCode;},CLASS_NAME:"OpenLayers.Projection"});OpenLayers.Projection.transforms={};OpenLayers.Projection.defaults={"EPSG:4326":{units:"degrees",maxExtent:[-180,-90,180,90],yx:true},"CRS:84":{units:"degrees",maxExtent:[-180,-90,180,90]},"EPSG:900913":{units:"m",maxExtent:[-20037508.34,-20037508.34,20037508.34,20037508.34]}};OpenLayers.Projection.addTransform=function(from,to,method){if(method===OpenLayers.Projection.nullTransform){var defaults=OpenLayers.Projection.defaults[from];if(defaults&&!OpenLayers.Projection.defaults[to]){OpenLayers.Projection.defaults[to]=defaults;}}
+if(!OpenLayers.Projection.transforms[from]){OpenLayers.Projection.transforms[from]={};}
+OpenLayers.Projection.transforms[from][to]=method;};OpenLayers.Projection.transform=function(point,source,dest){if(source&&dest){if(!(source instanceof OpenLayers.Projection)){source=new OpenLayers.Projection(source);}
+if(!(dest instanceof OpenLayers.Projection)){dest=new OpenLayers.Projection(dest);}
+if(source.proj&&dest.proj){point=Proj4js.transform(source.proj,dest.proj,point);}else{var sourceCode=source.getCode();var destCode=dest.getCode();var transforms=OpenLayers.Projection.transforms;if(transforms[sourceCode]&&transforms[sourceCode][destCode]){transforms[sourceCode][destCode](point);}}}
+return point;};OpenLayers.Projection.nullTransform=function(point){return point;};(function(){var pole=20037508.34;function inverseMercator(xy){xy.x=180*xy.x/pole;xy.y=180/Math.PI*(2*Math.atan(Math.exp((xy.y/pole)*Math.PI))-Math.PI/2);return xy;}
+function forwardMercator(xy){xy.x=xy.x*pole/180;xy.y=Math.log(Math.tan((90+xy.y)*Math.PI/360))/Math.PI*pole;return xy;}
+function map(base,codes){var add=OpenLayers.Projection.addTransform;var same=OpenLayers.Projection.nullTransform;var i,len,code,other,j;for(i=0,len=codes.length;i<len;++i){code=codes[i];add(base,code,forwardMercator);add(code,base,inverseMercator);for(j=i+1;j<len;++j){other=codes[j];add(code,other,same);add(other,code,same);}}}
+var mercator=["EPSG:900913","EPSG:3857","EPSG:102113","EPSG:102100"],geographic=["CRS:84","urn:ogc:def:crs:EPSG:6.6:4326","EPSG:4326"],i;for(i=mercator.length-1;i>=0;--i){map(mercator[i],geographic);}
+for(i=geographic.length-1;i>=0;--i){map(geographic[i],mercator);}})();OpenLayers.Map=OpenLayers.Class({Z_INDEX_BASE:{BaseLayer:100,Overlay:325,Feature:725,Popup:750,Control:1000},id:null,fractionalZoom:false,events:null,allOverlays:false,div:null,dragging:false,size:null,viewPortDiv:null,layerContainerOrigin:null,layerContainerDiv:null,layers:null,controls:null,popups:null,baseLayer:null,center:null,resolution:null,zoom:0,panRatio:1.5,options:null,tileSize:null,projection:"EPSG:4326",units:null,resolutions:null,maxResolution:null,minResolution:null,maxScale:null,minScale:null,maxExtent:null,minExtent:null,restrictedExtent:null,numZoomLevels:16,theme:null,displayProjection:null,fallThrough:true,panTween:null,eventListeners:null,panMethod:OpenLayers.Easing.Expo.easeOut,panDuration:50,paddingForPopups:null,minPx:null,maxPx:null,initialize:function(div,options){if(arguments.length===1&&typeof div==="object"){options=div;div=options&&options.div;}
+this.tileSize=new OpenLayers.Size(OpenLayers.Map.TILE_WIDTH,OpenLayers.Map.TILE_HEIGHT);this.paddingForPopups=new OpenLayers.Bounds(15,15,15,15);this.theme=OpenLayers._getScriptLocation()+'theme/default/style.css';this.options=OpenLayers.Util.extend({},options);OpenLayers.Util.extend(this,options);var projCode=this.projection instanceof OpenLayers.Projection?this.projection.projCode:this.projection;OpenLayers.Util.applyDefaults(this,OpenLayers.Projection.defaults[projCode]);if(this.maxExtent&&!(this.maxExtent instanceof OpenLayers.Bounds)){this.maxExtent=new OpenLayers.Bounds(this.maxExtent);}
+if(this.minExtent&&!(this.minExtent instanceof OpenLayers.Bounds)){this.minExtent=new OpenLayers.Bounds(this.minExtent);}
+if(this.restrictedExtent&&!(this.restrictedExtent instanceof OpenLayers.Bounds)){this.restrictedExtent=new OpenLayers.Bounds(this.restrictedExtent);}
+if(this.center&&!(this.center instanceof OpenLayers.LonLat)){this.center=new OpenLayers.LonLat(this.center);}
+this.layers=[];this.id=OpenLayers.Util.createUniqueID("OpenLayers.Map_");this.div=OpenLayers.Util.getElement(div);if(!this.div){this.div=document.createElement("div");this.div.style.height="1px";this.div.style.width="1px";}
+OpenLayers.Element.addClass(this.div,'olMap');var id=this.id+"_OpenLayers_ViewPort";this.viewPortDiv=OpenLayers.Util.createDiv(id,null,null,null,"relative",null,"hidden");this.viewPortDiv.style.width="100%";this.viewPortDiv.style.height="100%";this.viewPortDiv.className="olMapViewport";this.div.appendChild(this.viewPortDiv);this.events=new OpenLayers.Events(this,this.viewPortDiv,null,this.fallThrough,{includeXY:true});id=this.id+"_OpenLayers_Container";this.layerContainerDiv=OpenLayers.Util.createDiv(id);this.layerContainerDiv.style.width='100px';this.layerContainerDiv.style.height='100px';this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1;this.viewPortDiv.appendChild(this.layerContainerDiv);this.updateSize();if(this.eventListeners instanceof Object){this.events.on(this.eventListeners);}
+if(parseFloat(navigator.appVersion.split("MSIE")[1])<9){this.events.register("resize",this,this.updateSize);}else{this.updateSizeDestroy=OpenLayers.Function.bind(this.updateSize,this);OpenLayers.Event.observe(window,'resize',this.updateSizeDestroy);}
+if(this.theme){var addNode=true;var nodes=document.getElementsByTagName('link');for(var i=0,len=nodes.length;i<len;++i){if(OpenLayers.Util.isEquivalentUrl(nodes.item(i).href,this.theme)){addNode=false;break;}}
+if(addNode){var cssNode=document.createElement('link');cssNode.setAttribute('rel','stylesheet');cssNode.setAttribute('type','text/css');cssNode.setAttribute('href',this.theme);document.getElementsByTagName('head')[0].appendChild(cssNode);}}
+if(this.controls==null){this.controls=[];if(OpenLayers.Control!=null){if(OpenLayers.Control.Navigation){this.controls.push(new OpenLayers.Control.Navigation());}else if(OpenLayers.Control.TouchNavigation){this.controls.push(new OpenLayers.Control.TouchNavigation());}
+if(OpenLayers.Control.Zoom){this.controls.push(new OpenLayers.Control.Zoom());}else if(OpenLayers.Control.PanZoom){this.controls.push(new OpenLayers.Control.PanZoom());}
+if(OpenLayers.Control.ArgParser){this.controls.push(new OpenLayers.Control.ArgParser());}
+if(OpenLayers.Control.Attribution){this.controls.push(new OpenLayers.Control.Attribution());}}}
+for(var i=0,len=this.controls.length;i<len;i++){this.addControlToMap(this.controls[i]);}
+this.popups=[];this.unloadDestroy=OpenLayers.Function.bind(this.destroy,this);OpenLayers.Event.observe(window,'unload',this.unloadDestroy);if(options&&options.layers){delete this.center;this.addLayers(options.layers);if(options.center&&!this.getCenter()){this.setCenter(options.center,options.zoom);}}},getViewport:function(){return this.viewPortDiv;},render:function(div){this.div=OpenLayers.Util.getElement(div);OpenLayers.Element.addClass(this.div,'olMap');this.viewPortDiv.parentNode.removeChild(this.viewPortDiv);this.div.appendChild(this.viewPortDiv);this.updateSize();},unloadDestroy:null,updateSizeDestroy:null,destroy:function(){if(!this.unloadDestroy){return false;}
+if(this.panTween){this.panTween.stop();this.panTween=null;}
+OpenLayers.Event.stopObserving(window,'unload',this.unloadDestroy);this.unloadDestroy=null;if(this.updateSizeDestroy){OpenLayers.Event.stopObserving(window,'resize',this.updateSizeDestroy);}else{this.events.unregister("resize",this,this.updateSize);}
+this.paddingForPopups=null;if(this.controls!=null){for(var i=this.controls.length-1;i>=0;--i){this.controls[i].destroy();}
+this.controls=null;}
+if(this.layers!=null){for(var i=this.layers.length-1;i>=0;--i){this.layers[i].destroy(false);}
+this.layers=null;}
+if(this.viewPortDiv){this.div.removeChild(this.viewPortDiv);}
+this.viewPortDiv=null;if(this.eventListeners){this.events.un(this.eventListeners);this.eventListeners=null;}
+this.events.destroy();this.events=null;this.options=null;},setOptions:function(options){var updatePxExtent=this.minPx&&options.restrictedExtent!=this.restrictedExtent;OpenLayers.Util.extend(this,options);updatePxExtent&&this.moveTo(this.getCachedCenter(),this.zoom,{forceZoomChange:true});},getTileSize:function(){return this.tileSize;},getBy:function(array,property,match){var test=(typeof match.test=="function");var found=OpenLayers.Array.filter(this[array],function(item){return item[property]==match||(test&&match.test(item[property]));});return found;},getLayersBy:function(property,match){return this.getBy("layers",property,match);},getLayersByName:function(match){return this.getLayersBy("name",match);},getLayersByClass:function(match){return this.getLayersBy("CLASS_NAME",match);},getControlsBy:function(property,match){return this.getBy("controls",property,match);},getControlsByClass:function(match){return this.getControlsBy("CLASS_NAME",match);},getLayer:function(id){var foundLayer=null;for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];if(layer.id==id){foundLayer=layer;break;}}
+return foundLayer;},setLayerZIndex:function(layer,zIdx){layer.setZIndex(this.Z_INDEX_BASE[layer.isBaseLayer?'BaseLayer':'Overlay']
++zIdx*5);},resetLayersZIndex:function(){for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];this.setLayerZIndex(layer,i);}},addLayer:function(layer){for(var i=0,len=this.layers.length;i<len;i++){if(this.layers[i]==layer){return false;}}
+if(this.events.triggerEvent("preaddlayer",{layer:layer})===false){return false;}
+if(this.allOverlays){layer.isBaseLayer=false;}
+layer.div.className="olLayerDiv";layer.div.style.overflow="";this.setLayerZIndex(layer,this.layers.length);if(layer.isFixed){this.viewPortDiv.appendChild(layer.div);}else{this.layerContainerDiv.appendChild(layer.div);}
+this.layers.push(layer);layer.setMap(this);if(layer.isBaseLayer||(this.allOverlays&&!this.baseLayer)){if(this.baseLayer==null){this.setBaseLayer(layer);}else{layer.setVisibility(false);}}else{layer.redraw();}
+this.events.triggerEvent("addlayer",{layer:layer});layer.events.triggerEvent("added",{map:this,layer:layer});layer.afterAdd();return true;},addLayers:function(layers){for(var i=0,len=layers.length;i<len;i++){this.addLayer(layers[i]);}},removeLayer:function(layer,setNewBaseLayer){if(this.events.triggerEvent("preremovelayer",{layer:layer})===false){return;}
+if(setNewBaseLayer==null){setNewBaseLayer=true;}
+if(layer.isFixed){this.viewPortDiv.removeChild(layer.div);}else{this.layerContainerDiv.removeChild(layer.div);}
+OpenLayers.Util.removeItem(this.layers,layer);layer.removeMap(this);layer.map=null;if(this.baseLayer==layer){this.baseLayer=null;if(setNewBaseLayer){for(var i=0,len=this.layers.length;i<len;i++){var iLayer=this.layers[i];if(iLayer.isBaseLayer||this.allOverlays){this.setBaseLayer(iLayer);break;}}}}
+this.resetLayersZIndex();this.events.triggerEvent("removelayer",{layer:layer});layer.events.triggerEvent("removed",{map:this,layer:layer});},getNumLayers:function(){return this.layers.length;},getLayerIndex:function(layer){return OpenLayers.Util.indexOf(this.layers,layer);},setLayerIndex:function(layer,idx){var base=this.getLayerIndex(layer);if(idx<0){idx=0;}else if(idx>this.layers.length){idx=this.layers.length;}
+if(base!=idx){this.layers.splice(base,1);this.layers.splice(idx,0,layer);for(var i=0,len=this.layers.length;i<len;i++){this.setLayerZIndex(this.layers[i],i);}
+this.events.triggerEvent("changelayer",{layer:layer,property:"order"});if(this.allOverlays){if(idx===0){this.setBaseLayer(layer);}else if(this.baseLayer!==this.layers[0]){this.setBaseLayer(this.layers[0]);}}}},raiseLayer:function(layer,delta){var idx=this.getLayerIndex(layer)+delta;this.setLayerIndex(layer,idx);},setBaseLayer:function(newBaseLayer){if(newBaseLayer!=this.baseLayer){if(OpenLayers.Util.indexOf(this.layers,newBaseLayer)!=-1){var center=this.getCachedCenter();var newResolution=OpenLayers.Util.getResolutionFromScale(this.getScale(),newBaseLayer.units);if(this.baseLayer!=null&&!this.allOverlays){this.baseLayer.setVisibility(false);}
+this.baseLayer=newBaseLayer;if(!this.allOverlays||this.baseLayer.visibility){this.baseLayer.setVisibility(true);if(this.baseLayer.inRange===false){this.baseLayer.redraw();}}
+if(center!=null){var newZoom=this.getZoomForResolution(newResolution||this.resolution,true);this.setCenter(center,newZoom,false,true);}
+this.events.triggerEvent("changebaselayer",{layer:this.baseLayer});}}},addControl:function(control,px){this.controls.push(control);this.addControlToMap(control,px);},addControls:function(controls,pixels){var pxs=(arguments.length===1)?[]:pixels;for(var i=0,len=controls.length;i<len;i++){var ctrl=controls[i];var px=(pxs[i])?pxs[i]:null;this.addControl(ctrl,px);}},addControlToMap:function(control,px){control.outsideViewport=(control.div!=null);if(this.displayProjection&&!control.displayProjection){control.displayProjection=this.displayProjection;}
+control.setMap(this);var div=control.draw(px);if(div){if(!control.outsideViewport){div.style.zIndex=this.Z_INDEX_BASE['Control']+
+this.controls.length;this.viewPortDiv.appendChild(div);}}
+if(control.autoActivate){control.activate();}},getControl:function(id){var returnControl=null;for(var i=0,len=this.controls.length;i<len;i++){var control=this.controls[i];if(control.id==id){returnControl=control;break;}}
+return returnControl;},removeControl:function(control){if((control)&&(control==this.getControl(control.id))){if(control.div&&(control.div.parentNode==this.viewPortDiv)){this.viewPortDiv.removeChild(control.div);}
+OpenLayers.Util.removeItem(this.controls,control);}},addPopup:function(popup,exclusive){if(exclusive){for(var i=this.popups.length-1;i>=0;--i){this.removePopup(this.popups[i]);}}
+popup.map=this;this.popups.push(popup);var popupDiv=popup.draw();if(popupDiv){popupDiv.style.zIndex=this.Z_INDEX_BASE['Popup']+
+this.popups.length;this.layerContainerDiv.appendChild(popupDiv);}},removePopup:function(popup){OpenLayers.Util.removeItem(this.popups,popup);if(popup.div){try{this.layerContainerDiv.removeChild(popup.div);}
+catch(e){}}
+popup.map=null;},getSize:function(){var size=null;if(this.size!=null){size=this.size.clone();}
+return size;},updateSize:function(){var newSize=this.getCurrentSize();if(newSize&&!isNaN(newSize.h)&&!isNaN(newSize.w)){this.events.clearMouseCache();var oldSize=this.getSize();if(oldSize==null){this.size=oldSize=newSize;}
+if(!newSize.equals(oldSize)){this.size=newSize;for(var i=0,len=this.layers.length;i<len;i++){this.layers[i].onMapResize();}
+var center=this.getCachedCenter();if(this.baseLayer!=null&&center!=null){var zoom=this.getZoom();this.zoom=null;this.setCenter(center,zoom);}}}},getCurrentSize:function(){var size=new OpenLayers.Size(this.div.clientWidth,this.div.clientHeight);if(size.w==0&&size.h==0||isNaN(size.w)&&isNaN(size.h)){size.w=this.div.offsetWidth;size.h=this.div.offsetHeight;}
+if(size.w==0&&size.h==0||isNaN(size.w)&&isNaN(size.h)){size.w=parseInt(this.div.style.width);size.h=parseInt(this.div.style.height);}
+return size;},calculateBounds:function(center,resolution){var extent=null;if(center==null){center=this.getCachedCenter();}
+if(resolution==null){resolution=this.getResolution();}
+if((center!=null)&&(resolution!=null)){var halfWDeg=(this.size.w*resolution)/2;var halfHDeg=(this.size.h*resolution)/2;extent=new OpenLayers.Bounds(center.lon-halfWDeg,center.lat-halfHDeg,center.lon+halfWDeg,center.lat+halfHDeg);}
+return extent;},getCenter:function(){var center=null;var cachedCenter=this.getCachedCenter();if(cachedCenter){center=cachedCenter.clone();}
+return center;},getCachedCenter:function(){if(!this.center&&this.size){this.center=this.getLonLatFromViewPortPx({x:this.size.w/2,y:this.size.h/2});}
+return this.center;},getZoom:function(){return this.zoom;},pan:function(dx,dy,options){options=OpenLayers.Util.applyDefaults(options,{animate:true,dragging:false});if(options.dragging){if(dx!=0||dy!=0){this.moveByPx(dx,dy);}}else{var centerPx=this.getViewPortPxFromLonLat(this.getCachedCenter());var newCenterPx=centerPx.add(dx,dy);if(this.dragging||!newCenterPx.equals(centerPx)){var newCenterLonLat=this.getLonLatFromViewPortPx(newCenterPx);if(options.animate){this.panTo(newCenterLonLat);}else{this.moveTo(newCenterLonLat);if(this.dragging){this.dragging=false;this.events.triggerEvent("moveend");}}}}},panTo:function(lonlat){if(this.panMethod&&this.getExtent().scale(this.panRatio).containsLonLat(lonlat)){if(!this.panTween){this.panTween=new OpenLayers.Tween(this.panMethod);}
+var center=this.getCachedCenter();if(lonlat.equals(center)){return;}
+var from=this.getPixelFromLonLat(center);var to=this.getPixelFromLonLat(lonlat);var vector={x:to.x-from.x,y:to.y-from.y};var last={x:0,y:0};this.panTween.start({x:0,y:0},vector,this.panDuration,{callbacks:{eachStep:OpenLayers.Function.bind(function(px){var x=px.x-last.x,y=px.y-last.y;this.moveByPx(x,y);last.x=Math.round(px.x);last.y=Math.round(px.y);},this),done:OpenLayers.Function.bind(function(px){this.moveTo(lonlat);this.dragging=false;this.events.triggerEvent("moveend");},this)}});}else{this.setCenter(lonlat);}},setCenter:function(lonlat,zoom,dragging,forceZoomChange){this.panTween&&this.panTween.stop();this.moveTo(lonlat,zoom,{'dragging':dragging,'forceZoomChange':forceZoomChange});},moveByPx:function(dx,dy){var hw=this.size.w/2;var hh=this.size.h/2;var x=hw+dx;var y=hh+dy;var wrapDateLine=this.baseLayer.wrapDateLine;var xRestriction=0;var yRestriction=0;if(this.restrictedExtent){xRestriction=hw;yRestriction=hh;wrapDateLine=false;}
+dx=wrapDateLine||x<=this.maxPx.x-xRestriction&&x>=this.minPx.x+xRestriction?Math.round(dx):0;dy=y<=this.maxPx.y-yRestriction&&y>=this.minPx.y+yRestriction?Math.round(dy):0;if(dx||dy){if(!this.dragging){this.dragging=true;this.events.triggerEvent("movestart");}
+this.center=null;if(dx){this.layerContainerDiv.style.left=parseInt(this.layerContainerDiv.style.left)-dx+"px";this.minPx.x-=dx;this.maxPx.x-=dx;}
+if(dy){this.layerContainerDiv.style.top=parseInt(this.layerContainerDiv.style.top)-dy+"px";this.minPx.y-=dy;this.maxPx.y-=dy;}
+var layer,i,len;for(i=0,len=this.layers.length;i<len;++i){layer=this.layers[i];if(layer.visibility&&(layer===this.baseLayer||layer.inRange)){layer.moveByPx(dx,dy);layer.events.triggerEvent("move");}}
+this.events.triggerEvent("move");}},adjustZoom:function(zoom){var resolution,resolutions=this.baseLayer.resolutions,maxResolution=this.getMaxExtent().getWidth()/this.size.w;if(this.getResolutionForZoom(zoom)>maxResolution){for(var i=zoom|0,ii=resolutions.length;i<ii;++i){if(resolutions[i]<=maxResolution){zoom=i;break;}}}
+return zoom;},moveTo:function(lonlat,zoom,options){if(lonlat!=null&&!(lonlat instanceof OpenLayers.LonLat)){lonlat=new OpenLayers.LonLat(lonlat);}
+if(!options){options={};}
+if(zoom!=null){zoom=parseFloat(zoom);if(!this.fractionalZoom){zoom=Math.round(zoom);}}
+if(this.baseLayer.wrapDateLine){var requestedZoom=zoom;zoom=this.adjustZoom(zoom);if(zoom!==requestedZoom){lonlat=this.getCenter();}}
+var dragging=options.dragging||this.dragging;var forceZoomChange=options.forceZoomChange;if(!this.getCachedCenter()&&!this.isValidLonLat(lonlat)){lonlat=this.maxExtent.getCenterLonLat();this.center=lonlat.clone();}
+if(this.restrictedExtent!=null){if(lonlat==null){lonlat=this.center;}
+if(zoom==null){zoom=this.getZoom();}
+var resolution=this.getResolutionForZoom(zoom);var extent=this.calculateBounds(lonlat,resolution);if(!this.restrictedExtent.containsBounds(extent)){var maxCenter=this.restrictedExtent.getCenterLonLat();if(extent.getWidth()>this.restrictedExtent.getWidth()){lonlat=new OpenLayers.LonLat(maxCenter.lon,lonlat.lat);}else if(extent.left<this.restrictedExtent.left){lonlat=lonlat.add(this.restrictedExtent.left-
+extent.left,0);}else if(extent.right>this.restrictedExtent.right){lonlat=lonlat.add(this.restrictedExtent.right-
+extent.right,0);}
+if(extent.getHeight()>this.restrictedExtent.getHeight()){lonlat=new OpenLayers.LonLat(lonlat.lon,maxCenter.lat);}else if(extent.bottom<this.restrictedExtent.bottom){lonlat=lonlat.add(0,this.restrictedExtent.bottom-
+extent.bottom);}
+else if(extent.top>this.restrictedExtent.top){lonlat=lonlat.add(0,this.restrictedExtent.top-
+extent.top);}}}
+var zoomChanged=forceZoomChange||((this.isValidZoomLevel(zoom))&&(zoom!=this.getZoom()));var centerChanged=(this.isValidLonLat(lonlat))&&(!lonlat.equals(this.center));if(zoomChanged||centerChanged||dragging){dragging||this.events.triggerEvent("movestart");if(centerChanged){if(!zoomChanged&&this.center){this.centerLayerContainer(lonlat);}
+this.center=lonlat.clone();}
+var res=zoomChanged?this.getResolutionForZoom(zoom):this.getResolution();if(zoomChanged||this.layerContainerOrigin==null){this.layerContainerOrigin=this.getCachedCenter();this.layerContainerDiv.style.left="0px";this.layerContainerDiv.style.top="0px";var maxExtent=this.getMaxExtent({restricted:true});var maxExtentCenter=maxExtent.getCenterLonLat();var lonDelta=this.center.lon-maxExtentCenter.lon;var latDelta=maxExtentCenter.lat-this.center.lat;var extentWidth=Math.round(maxExtent.getWidth()/res);var extentHeight=Math.round(maxExtent.getHeight()/res);this.minPx={x:(this.size.w-extentWidth)/2-lonDelta/res,y:(this.size.h-extentHeight)/2-latDelta/res};this.maxPx={x:this.minPx.x+Math.round(maxExtent.getWidth()/res),y:this.minPx.y+Math.round(maxExtent.getHeight()/res)};}
+if(zoomChanged){this.zoom=zoom;this.resolution=res;}
+var bounds=this.getExtent();if(this.baseLayer.visibility){this.baseLayer.moveTo(bounds,zoomChanged,options.dragging);options.dragging||this.baseLayer.events.triggerEvent("moveend",{zoomChanged:zoomChanged});}
+bounds=this.baseLayer.getExtent();for(var i=this.layers.length-1;i>=0;--i){var layer=this.layers[i];if(layer!==this.baseLayer&&!layer.isBaseLayer){var inRange=layer.calculateInRange();if(layer.inRange!=inRange){layer.inRange=inRange;if(!inRange){layer.display(false);}
+this.events.triggerEvent("changelayer",{layer:layer,property:"visibility"});}
+if(inRange&&layer.visibility){layer.moveTo(bounds,zoomChanged,options.dragging);options.dragging||layer.events.triggerEvent("moveend",{zoomChanged:zoomChanged});}}}
+this.events.triggerEvent("move");dragging||this.events.triggerEvent("moveend");if(zoomChanged){for(var i=0,len=this.popups.length;i<len;i++){this.popups[i].updatePosition();}
+this.events.triggerEvent("zoomend");}}},centerLayerContainer:function(lonlat){var originPx=this.getViewPortPxFromLonLat(this.layerContainerOrigin);var newPx=this.getViewPortPxFromLonLat(lonlat);if((originPx!=null)&&(newPx!=null)){var oldLeft=parseInt(this.layerContainerDiv.style.left);var oldTop=parseInt(this.layerContainerDiv.style.top);var newLeft=Math.round(originPx.x-newPx.x);var newTop=Math.round(originPx.y-newPx.y);this.layerContainerDiv.style.left=newLeft+"px";this.layerContainerDiv.style.top=newTop+"px";var dx=oldLeft-newLeft;var dy=oldTop-newTop;this.minPx.x-=dx;this.maxPx.x-=dx;this.minPx.y-=dy;this.maxPx.y-=dy;}},isValidZoomLevel:function(zoomLevel){return((zoomLevel!=null)&&(zoomLevel>=0)&&(zoomLevel<this.getNumZoomLevels()));},isValidLonLat:function(lonlat){var valid=false;if(lonlat!=null){var maxExtent=this.getMaxExtent();var worldBounds=this.baseLayer.wrapDateLine&&maxExtent;valid=maxExtent.containsLonLat(lonlat,{worldBounds:worldBounds});}
+return valid;},getProjection:function(){var projection=this.getProjectionObject();return projection?projection.getCode():null;},getProjectionObject:function(){var projection=null;if(this.baseLayer!=null){projection=this.baseLayer.projection;}
+return projection;},getMaxResolution:function(){var maxResolution=null;if(this.baseLayer!=null){maxResolution=this.baseLayer.maxResolution;}
+return maxResolution;},getMaxExtent:function(options){var maxExtent=null;if(options&&options.restricted&&this.restrictedExtent){maxExtent=this.restrictedExtent;}else if(this.baseLayer!=null){maxExtent=this.baseLayer.maxExtent;}
+return maxExtent;},getNumZoomLevels:function(){var numZoomLevels=null;if(this.baseLayer!=null){numZoomLevels=this.baseLayer.numZoomLevels;}
+return numZoomLevels;},getExtent:function(){var extent=null;if(this.baseLayer!=null){extent=this.baseLayer.getExtent();}
+return extent;},getResolution:function(){var resolution=null;if(this.baseLayer!=null){resolution=this.baseLayer.getResolution();}else if(this.allOverlays===true&&this.layers.length>0){resolution=this.layers[0].getResolution();}
+return resolution;},getUnits:function(){var units=null;if(this.baseLayer!=null){units=this.baseLayer.units;}
+return units;},getScale:function(){var scale=null;if(this.baseLayer!=null){var res=this.getResolution();var units=this.baseLayer.units;scale=OpenLayers.Util.getScaleFromResolution(res,units);}
+return scale;},getZoomForExtent:function(bounds,closest){var zoom=null;if(this.baseLayer!=null){zoom=this.baseLayer.getZoomForExtent(bounds,closest);}
+return zoom;},getResolutionForZoom:function(zoom){var resolution=null;if(this.baseLayer){resolution=this.baseLayer.getResolutionForZoom(zoom);}
+return resolution;},getZoomForResolution:function(resolution,closest){var zoom=null;if(this.baseLayer!=null){zoom=this.baseLayer.getZoomForResolution(resolution,closest);}
+return zoom;},zoomTo:function(zoom){if(this.isValidZoomLevel(zoom)){this.setCenter(null,zoom);}},zoomIn:function(){this.zoomTo(this.getZoom()+1);},zoomOut:function(){this.zoomTo(this.getZoom()-1);},zoomToExtent:function(bounds,closest){if(!(bounds instanceof OpenLayers.Bounds)){bounds=new OpenLayers.Bounds(bounds);}
+var center=bounds.getCenterLonLat();if(this.baseLayer.wrapDateLine){var maxExtent=this.getMaxExtent();bounds=bounds.clone();while(bounds.right<bounds.left){bounds.right+=maxExtent.getWidth();}
+center=bounds.getCenterLonLat().wrapDateLine(maxExtent);}
+this.setCenter(center,this.getZoomForExtent(bounds,closest));},zoomToMaxExtent:function(options){var restricted=(options)?options.restricted:true;var maxExtent=this.getMaxExtent({'restricted':restricted});this.zoomToExtent(maxExtent);},zoomToScale:function(scale,closest){var res=OpenLayers.Util.getResolutionFromScale(scale,this.baseLayer.units);var halfWDeg=(this.size.w*res)/2;var halfHDeg=(this.size.h*res)/2;var center=this.getCachedCenter();var extent=new OpenLayers.Bounds(center.lon-halfWDeg,center.lat-halfHDeg,center.lon+halfWDeg,center.lat+halfHDeg);this.zoomToExtent(extent,closest);},getLonLatFromViewPortPx:function(viewPortPx){var lonlat=null;if(this.baseLayer!=null){lonlat=this.baseLayer.getLonLatFromViewPortPx(viewPortPx);}
+return lonlat;},getViewPortPxFromLonLat:function(lonlat){var px=null;if(this.baseLayer!=null){px=this.baseLayer.getViewPortPxFromLonLat(lonlat);}
+return px;},getLonLatFromPixel:function(px){return this.getLonLatFromViewPortPx(px);},getPixelFromLonLat:function(lonlat){var px=this.getViewPortPxFromLonLat(lonlat);px.x=Math.round(px.x);px.y=Math.round(px.y);return px;},getGeodesicPixelSize:function(px){var lonlat=px?this.getLonLatFromPixel(px):(this.getCachedCenter()||new OpenLayers.LonLat(0,0));var res=this.getResolution();var left=lonlat.add(-res/2,0);var right=lonlat.add(res/2,0);var bottom=lonlat.add(0,-res/2);var top=lonlat.add(0,res/2);var dest=new OpenLayers.Projection("EPSG:4326");var source=this.getProjectionObject()||dest;if(!source.equals(dest)){left.transform(source,dest);right.transform(source,dest);bottom.transform(source,dest);top.transform(source,dest);}
+return new OpenLayers.Size(OpenLayers.Util.distVincenty(left,right),OpenLayers.Util.distVincenty(bottom,top));},getViewPortPxFromLayerPx:function(layerPx){var viewPortPx=null;if(layerPx!=null){var dX=parseInt(this.layerContainerDiv.style.left);var dY=parseInt(this.layerContainerDiv.style.top);viewPortPx=layerPx.add(dX,dY);}
+return viewPortPx;},getLayerPxFromViewPortPx:function(viewPortPx){var layerPx=null;if(viewPortPx!=null){var dX=-parseInt(this.layerContainerDiv.style.left);var dY=-parseInt(this.layerContainerDiv.style.top);layerPx=viewPortPx.add(dX,dY);if(isNaN(layerPx.x)||isNaN(layerPx.y)){layerPx=null;}}
+return layerPx;},getLonLatFromLayerPx:function(px){px=this.getViewPortPxFromLayerPx(px);return this.getLonLatFromViewPortPx(px);},getLayerPxFromLonLat:function(lonlat){var px=this.getPixelFromLonLat(lonlat);return this.getLayerPxFromViewPortPx(px);},CLASS_NAME:"OpenLayers.Map"});OpenLayers.Map.TILE_WIDTH=256;OpenLayers.Map.TILE_HEIGHT=256;OpenLayers.Layer=OpenLayers.Class({id:null,name:null,div:null,opacity:1,alwaysInRange:null,RESOLUTION_PROPERTIES:['scales','resolutions','maxScale','minScale','maxResolution','minResolution','numZoomLevels','maxZoomLevel'],events:null,map:null,isBaseLayer:false,alpha:false,displayInLayerSwitcher:true,visibility:true,attribution:null,inRange:false,imageSize:null,options:null,eventListeners:null,gutter:0,projection:null,units:null,scales:null,resolutions:null,maxExtent:null,minExtent:null,maxResolution:null,minResolution:null,numZoomLevels:null,minScale:null,maxScale:null,displayOutsideMaxExtent:false,wrapDateLine:false,metadata:null,initialize:function(name,options){this.metadata={};this.addOptions(options);this.name=name;if(this.id==null){this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");this.div=OpenLayers.Util.createDiv(this.id);this.div.style.width="100%";this.div.style.height="100%";this.div.dir="ltr";this.events=new OpenLayers.Events(this,this.div);if(this.eventListeners instanceof Object){this.events.on(this.eventListeners);}}},destroy:function(setNewBaseLayer){if(setNewBaseLayer==null){setNewBaseLayer=true;}
+if(this.map!=null){this.map.removeLayer(this,setNewBaseLayer);}
+this.projection=null;this.map=null;this.name=null;this.div=null;this.options=null;if(this.events){if(this.eventListeners){this.events.un(this.eventListeners);}
+this.events.destroy();}
+this.eventListeners=null;this.events=null;},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer(this.name,this.getOptions());}
+OpenLayers.Util.applyDefaults(obj,this);obj.map=null;return obj;},getOptions:function(){var options={};for(var o in this.options){options[o]=this[o];}
+return options;},setName:function(newName){if(newName!=this.name){this.name=newName;if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"name"});}}},addOptions:function(newOptions,reinitialize){if(this.options==null){this.options={};}
+if(newOptions){if(typeof newOptions.projection=="string"){newOptions.projection=new OpenLayers.Projection(newOptions.projection);}
+if(newOptions.projection){OpenLayers.Util.applyDefaults(newOptions,OpenLayers.Projection.defaults[newOptions.projection.getCode()]);}
+if(newOptions.maxExtent&&!(newOptions.maxExtent instanceof OpenLayers.Bounds)){newOptions.maxExtent=new OpenLayers.Bounds(newOptions.maxExtent);}
+if(newOptions.minExtent&&!(newOptions.minExtent instanceof OpenLayers.Bounds)){newOptions.minExtent=new OpenLayers.Bounds(newOptions.minExtent);}}
+OpenLayers.Util.extend(this.options,newOptions);OpenLayers.Util.extend(this,newOptions);if(this.projection&&this.projection.getUnits()){this.units=this.projection.getUnits();}
+if(this.map){var resolution=this.map.getResolution();var properties=this.RESOLUTION_PROPERTIES.concat(["projection","units","minExtent","maxExtent"]);for(var o in newOptions){if(newOptions.hasOwnProperty(o)&&OpenLayers.Util.indexOf(properties,o)>=0){this.initResolutions();if(reinitialize&&this.map.baseLayer===this){this.map.setCenter(this.map.getCenter(),this.map.getZoomForResolution(resolution),false,true);this.map.events.triggerEvent("changebaselayer",{layer:this});}
+break;}}}},onMapResize:function(){},redraw:function(){var redrawn=false;if(this.map){this.inRange=this.calculateInRange();var extent=this.getExtent();if(extent&&this.inRange&&this.visibility){var zoomChanged=true;this.moveTo(extent,zoomChanged,false);this.events.triggerEvent("moveend",{"zoomChanged":zoomChanged});redrawn=true;}}
+return redrawn;},moveTo:function(bounds,zoomChanged,dragging){var display=this.visibility;if(!this.isBaseLayer){display=display&&this.inRange;}
+this.display(display);},moveByPx:function(dx,dy){},setMap:function(map){if(this.map==null){this.map=map;this.maxExtent=this.maxExtent||this.map.maxExtent;this.minExtent=this.minExtent||this.map.minExtent;this.projection=this.projection||this.map.projection;if(typeof this.projection=="string"){this.projection=new OpenLayers.Projection(this.projection);}
+this.units=this.projection.getUnits()||this.units||this.map.units;this.initResolutions();if(!this.isBaseLayer){this.inRange=this.calculateInRange();var show=((this.visibility)&&(this.inRange));this.div.style.display=show?"":"none";}
+this.setTileSize();}},afterAdd:function(){},removeMap:function(map){},getImageSize:function(bounds){return(this.imageSize||this.tileSize);},setTileSize:function(size){var tileSize=(size)?size:((this.tileSize)?this.tileSize:this.map.getTileSize());this.tileSize=tileSize;if(this.gutter){this.imageSize=new OpenLayers.Size(tileSize.w+(2*this.gutter),tileSize.h+(2*this.gutter));}},getVisibility:function(){return this.visibility;},setVisibility:function(visibility){if(visibility!=this.visibility){this.visibility=visibility;this.display(visibility);this.redraw();if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"visibility"});}
+this.events.triggerEvent("visibilitychanged");}},display:function(display){if(display!=(this.div.style.display!="none")){this.div.style.display=(display&&this.calculateInRange())?"block":"none";}},calculateInRange:function(){var inRange=false;if(this.alwaysInRange){inRange=true;}else{if(this.map){var resolution=this.map.getResolution();inRange=((resolution>=this.minResolution)&&(resolution<=this.maxResolution));}}
+return inRange;},setIsBaseLayer:function(isBaseLayer){if(isBaseLayer!=this.isBaseLayer){this.isBaseLayer=isBaseLayer;if(this.map!=null){this.map.events.triggerEvent("changebaselayer",{layer:this});}}},initResolutions:function(){var i,len,p;var props={},alwaysInRange=true;for(i=0,len=this.RESOLUTION_PROPERTIES.length;i<len;i++){p=this.RESOLUTION_PROPERTIES[i];props[p]=this.options[p];if(alwaysInRange&&this.options[p]){alwaysInRange=false;}}
+if(this.alwaysInRange==null){this.alwaysInRange=alwaysInRange;}
+if(props.resolutions==null){props.resolutions=this.resolutionsFromScales(props.scales);}
+if(props.resolutions==null){props.resolutions=this.calculateResolutions(props);}
+if(props.resolutions==null){for(i=0,len=this.RESOLUTION_PROPERTIES.length;i<len;i++){p=this.RESOLUTION_PROPERTIES[i];props[p]=this.options[p]!=null?this.options[p]:this.map[p];}
+if(props.resolutions==null){props.resolutions=this.resolutionsFromScales(props.scales);}
+if(props.resolutions==null){props.resolutions=this.calculateResolutions(props);}}
+var maxResolution;if(this.options.maxResolution&&this.options.maxResolution!=="auto"){maxResolution=this.options.maxResolution;}
+if(this.options.minScale){maxResolution=OpenLayers.Util.getResolutionFromScale(this.options.minScale,this.units);}
+var minResolution;if(this.options.minResolution&&this.options.minResolution!=="auto"){minResolution=this.options.minResolution;}
+if(this.options.maxScale){minResolution=OpenLayers.Util.getResolutionFromScale(this.options.maxScale,this.units);}
+if(props.resolutions){props.resolutions.sort(function(a,b){return(b-a);});if(!maxResolution){maxResolution=props.resolutions[0];}
+if(!minResolution){var lastIdx=props.resolutions.length-1;minResolution=props.resolutions[lastIdx];}}
+this.resolutions=props.resolutions;if(this.resolutions){len=this.resolutions.length;this.scales=new Array(len);for(i=0;i<len;i++){this.scales[i]=OpenLayers.Util.getScaleFromResolution(this.resolutions[i],this.units);}
+this.numZoomLevels=len;}
+this.minResolution=minResolution;if(minResolution){this.maxScale=OpenLayers.Util.getScaleFromResolution(minResolution,this.units);}
+this.maxResolution=maxResolution;if(maxResolution){this.minScale=OpenLayers.Util.getScaleFromResolution(maxResolution,this.units);}},resolutionsFromScales:function(scales){if(scales==null){return;}
+var resolutions,i,len;len=scales.length;resolutions=new Array(len);for(i=0;i<len;i++){resolutions[i]=OpenLayers.Util.getResolutionFromScale(scales[i],this.units);}
+return resolutions;},calculateResolutions:function(props){var viewSize,wRes,hRes;var maxResolution=props.maxResolution;if(props.minScale!=null){maxResolution=OpenLayers.Util.getResolutionFromScale(props.minScale,this.units);}else if(maxResolution=="auto"&&this.maxExtent!=null){viewSize=this.map.getSize();wRes=this.maxExtent.getWidth()/viewSize.w;hRes=this.maxExtent.getHeight()/viewSize.h;maxResolution=Math.max(wRes,hRes);}
+var minResolution=props.minResolution;if(props.maxScale!=null){minResolution=OpenLayers.Util.getResolutionFromScale(props.maxScale,this.units);}else if(props.minResolution=="auto"&&this.minExtent!=null){viewSize=this.map.getSize();wRes=this.minExtent.getWidth()/viewSize.w;hRes=this.minExtent.getHeight()/viewSize.h;minResolution=Math.max(wRes,hRes);}
+if(typeof maxResolution!=="number"&&typeof minResolution!=="number"&&this.maxExtent!=null){var tileSize=this.map.getTileSize();maxResolution=Math.max(this.maxExtent.getWidth()/tileSize.w,this.maxExtent.getHeight()/tileSize.h);}
+var maxZoomLevel=props.maxZoomLevel;var numZoomLevels=props.numZoomLevels;if(typeof minResolution==="number"&&typeof maxResolution==="number"&&numZoomLevels===undefined){var ratio=maxResolution/minResolution;numZoomLevels=Math.floor(Math.log(ratio)/Math.log(2))+1;}else if(numZoomLevels===undefined&&maxZoomLevel!=null){numZoomLevels=maxZoomLevel+1;}
+if(typeof numZoomLevels!=="number"||numZoomLevels<=0||(typeof maxResolution!=="number"&&typeof minResolution!=="number")){return;}
+var resolutions=new Array(numZoomLevels);var base=2;if(typeof minResolution=="number"&&typeof maxResolution=="number"){base=Math.pow((maxResolution/minResolution),(1/(numZoomLevels-1)));}
+var i;if(typeof maxResolution==="number"){for(i=0;i<numZoomLevels;i++){resolutions[i]=maxResolution/Math.pow(base,i);}}else{for(i=0;i<numZoomLevels;i++){resolutions[numZoomLevels-1-i]=minResolution*Math.pow(base,i);}}
+return resolutions;},getResolution:function(){var zoom=this.map.getZoom();return this.getResolutionForZoom(zoom);},getExtent:function(){return this.map.calculateBounds();},getZoomForExtent:function(extent,closest){var viewSize=this.map.getSize();var idealResolution=Math.max(extent.getWidth()/viewSize.w,extent.getHeight()/viewSize.h);return this.getZoomForResolution(idealResolution,closest);},getDataExtent:function(){},getResolutionForZoom:function(zoom){zoom=Math.max(0,Math.min(zoom,this.resolutions.length-1));var resolution;if(this.map.fractionalZoom){var low=Math.floor(zoom);var high=Math.ceil(zoom);resolution=this.resolutions[low]-
+((zoom-low)*(this.resolutions[low]-this.resolutions[high]));}else{resolution=this.resolutions[Math.round(zoom)];}
+return resolution;},getZoomForResolution:function(resolution,closest){var zoom,i,len;if(this.map.fractionalZoom){var lowZoom=0;var highZoom=this.resolutions.length-1;var highRes=this.resolutions[lowZoom];var lowRes=this.resolutions[highZoom];var res;for(i=0,len=this.resolutions.length;i<len;++i){res=this.resolutions[i];if(res>=resolution){highRes=res;lowZoom=i;}
+if(res<=resolution){lowRes=res;highZoom=i;break;}}
+var dRes=highRes-lowRes;if(dRes>0){zoom=lowZoom+((highRes-resolution)/dRes);}else{zoom=lowZoom;}}else{var diff;var minDiff=Number.POSITIVE_INFINITY;for(i=0,len=this.resolutions.length;i<len;i++){if(closest){diff=Math.abs(this.resolutions[i]-resolution);if(diff>minDiff){break;}
+minDiff=diff;}else{if(this.resolutions[i]<resolution){break;}}}
+zoom=Math.max(0,i-1);}
+return zoom;},getLonLatFromViewPortPx:function(viewPortPx){var lonlat=null;var map=this.map;if(viewPortPx!=null&&map.minPx){var res=map.getResolution();var maxExtent=map.getMaxExtent({restricted:true});var lon=(viewPortPx.x-map.minPx.x)*res+maxExtent.left;var lat=(map.minPx.y-viewPortPx.y)*res+maxExtent.top;lonlat=new OpenLayers.LonLat(lon,lat);if(this.wrapDateLine){lonlat=lonlat.wrapDateLine(this.maxExtent);}}
+return lonlat;},getViewPortPxFromLonLat:function(lonlat,resolution){var px=null;if(lonlat!=null){resolution=resolution||this.map.getResolution();var extent=this.map.calculateBounds(null,resolution);px=new OpenLayers.Pixel((1/resolution*(lonlat.lon-extent.left)),(1/resolution*(extent.top-lonlat.lat)));}
+return px;},setOpacity:function(opacity){if(opacity!=this.opacity){this.opacity=opacity;var childNodes=this.div.childNodes;for(var i=0,len=childNodes.length;i<len;++i){var element=childNodes[i].firstChild||childNodes[i];var lastChild=childNodes[i].lastChild;if(lastChild&&lastChild.nodeName.toLowerCase()==="iframe"){element=lastChild.parentNode;}
+OpenLayers.Util.modifyDOMElement(element,null,null,null,null,null,null,opacity);}
+if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"opacity"});}}},getZIndex:function(){return this.div.style.zIndex;},setZIndex:function(zIndex){this.div.style.zIndex=zIndex;},adjustBounds:function(bounds){if(this.gutter){var mapGutter=this.gutter*this.map.getResolution();bounds=new OpenLayers.Bounds(bounds.left-mapGutter,bounds.bottom-mapGutter,bounds.right+mapGutter,bounds.top+mapGutter);}
+if(this.wrapDateLine){var wrappingOptions={'rightTolerance':this.getResolution(),'leftTolerance':this.getResolution()};bounds=bounds.wrapDateLine(this.maxExtent,wrappingOptions);}
+return bounds;},CLASS_NAME:"OpenLayers.Layer"});OpenLayers.Layer.HTTPRequest=OpenLayers.Class(OpenLayers.Layer,{URL_HASH_FACTOR:(Math.sqrt(5)-1)/2,url:null,params:null,reproject:false,initialize:function(name,url,params,options){OpenLayers.Layer.prototype.initialize.apply(this,[name,options]);this.url=url;if(!this.params){this.params=OpenLayers.Util.extend({},params);}},destroy:function(){this.url=null;this.params=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.HTTPRequest(this.name,this.url,this.params,this.getOptions());}
+obj=OpenLayers.Layer.prototype.clone.apply(this,[obj]);return obj;},setUrl:function(newUrl){this.url=newUrl;},mergeNewParams:function(newParams){this.params=OpenLayers.Util.extend(this.params,newParams);var ret=this.redraw();if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"params"});}
+return ret;},redraw:function(force){if(force){return this.mergeNewParams({"_olSalt":Math.random()});}else{return OpenLayers.Layer.prototype.redraw.apply(this,[]);}},selectUrl:function(paramString,urls){var product=1;for(var i=0,len=paramString.length;i<len;i++){product*=paramString.charCodeAt(i)*this.URL_HASH_FACTOR;product-=Math.floor(product);}
+return urls[Math.floor(product*urls.length)];},getFullRequestString:function(newParams,altUrl){var url=altUrl||this.url;var allParams=OpenLayers.Util.extend({},this.params);allParams=OpenLayers.Util.extend(allParams,newParams);var paramsString=OpenLayers.Util.getParameterString(allParams);if(OpenLayers.Util.isArray(url)){url=this.selectUrl(paramsString,url);}
+var urlParams=OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(url));for(var key in allParams){if(key.toUpperCase()in urlParams){delete allParams[key];}}
+paramsString=OpenLayers.Util.getParameterString(allParams);return OpenLayers.Util.urlAppend(url,paramsString);},CLASS_NAME:"OpenLayers.Layer.HTTPRequest"});OpenLayers.Tile=OpenLayers.Class({events:null,eventListeners:null,id:null,layer:null,url:null,bounds:null,size:null,position:null,isLoading:false,initialize:function(layer,position,bounds,url,size,options){this.layer=layer;this.position=position.clone();this.setBounds(bounds);this.url=url;if(size){this.size=size.clone();}
+this.id=OpenLayers.Util.createUniqueID("Tile_");OpenLayers.Util.extend(this,options);this.events=new OpenLayers.Events(this);if(this.eventListeners instanceof Object){this.events.on(this.eventListeners);}},unload:function(){if(this.isLoading){this.isLoading=false;this.events.triggerEvent("unload");}},destroy:function(){this.layer=null;this.bounds=null;this.size=null;this.position=null;if(this.eventListeners){this.events.un(this.eventListeners);}
+this.events.destroy();this.eventListeners=null;this.events=null;},draw:function(deferred){if(!deferred){this.clear();}
+var draw=this.shouldDraw();if(draw&&!deferred){draw=this.events.triggerEvent("beforedraw")!==false;}
+return draw;},shouldDraw:function(){var withinMaxExtent=false,maxExtent=this.layer.maxExtent;if(maxExtent){var map=this.layer.map;var worldBounds=map.baseLayer.wrapDateLine&&map.getMaxExtent();if(this.bounds.intersectsBounds(maxExtent,{inclusive:false,worldBounds:worldBounds})){withinMaxExtent=true;}}
+return withinMaxExtent||this.layer.displayOutsideMaxExtent;},setBounds:function(bounds){bounds=bounds.clone();if(this.layer.map.baseLayer.wrapDateLine){var worldExtent=this.layer.map.getMaxExtent(),tolerance=this.layer.map.getResolution();bounds=bounds.wrapDateLine(worldExtent,{leftTolerance:tolerance,rightTolerance:tolerance});}
+this.bounds=bounds;},moveTo:function(bounds,position,redraw){if(redraw==null){redraw=true;}
+this.setBounds(bounds);this.position=position.clone();if(redraw){this.draw();}},clear:function(draw){},CLASS_NAME:"OpenLayers.Tile"});OpenLayers.Tile.Image=OpenLayers.Class(OpenLayers.Tile,{url:null,imgDiv:null,frame:null,imageReloadAttempts:null,layerAlphaHack:null,asyncRequestId:null,blankImageUrl:"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAQAIBRAA7",maxGetUrlLength:null,canvasContext:null,crossOriginKeyword:null,initialize:function(layer,position,bounds,url,size,options){OpenLayers.Tile.prototype.initialize.apply(this,arguments);this.url=url;this.layerAlphaHack=this.layer.alpha&&OpenLayers.Util.alphaHack();if(this.maxGetUrlLength!=null||this.layer.gutter||this.layerAlphaHack){this.frame=document.createElement("div");this.frame.style.position="absolute";this.frame.style.overflow="hidden";}
+if(this.maxGetUrlLength!=null){OpenLayers.Util.extend(this,OpenLayers.Tile.Image.IFrame);}},destroy:function(){if(this.imgDiv){this.clear();this.imgDiv=null;this.frame=null;}
+this.asyncRequestId=null;OpenLayers.Tile.prototype.destroy.apply(this,arguments);},draw:function(){var drawn=OpenLayers.Tile.prototype.draw.apply(this,arguments);if(drawn){if(this.layer!=this.layer.map.baseLayer&&this.layer.reproject){this.bounds=this.getBoundsFromBaseLayer(this.position);}
+if(this.isLoading){this._loadEvent="reload";}else{this.isLoading=true;this._loadEvent="loadstart";}
+this.positionTile();this.renderTile();}else{this.unload();}
+return drawn;},renderTile:function(){this.layer.div.appendChild(this.getTile());if(this.layer.async){var id=this.asyncRequestId=(this.asyncRequestId||0)+1;this.layer.getURLasync(this.bounds,function(url){if(id==this.asyncRequestId){this.url=url;this.initImage();}},this);}else{this.url=this.layer.getURL(this.bounds);this.initImage();}},positionTile:function(){var style=this.getTile().style,size=this.frame?this.size:this.layer.getImageSize(this.bounds);style.left=this.position.x+"%";style.top=this.position.y+"%";style.width=size.w+"%";style.height=size.h+"%";},clear:function(){OpenLayers.Tile.prototype.clear.apply(this,arguments);var img=this.imgDiv;if(img){OpenLayers.Event.stopObservingElement(img);var tile=this.getTile();if(tile.parentNode===this.layer.div){this.layer.div.removeChild(tile);}
+this.setImgSrc();if(this.layerAlphaHack===true){img.style.filter="";}
+OpenLayers.Element.removeClass(img,"olImageLoadError");}
+this.canvasContext=null;},getImage:function(){if(!this.imgDiv){this.imgDiv=document.createElement("img");this.imgDiv.className="olTileImage";this.imgDiv.galleryImg="no";var style=this.imgDiv.style;if(this.frame){var left=0,top=0;if(this.layer.gutter){left=this.layer.gutter/this.layer.tileSize.w*100;top=this.layer.gutter/this.layer.tileSize.h*100;}
+style.left=-left+"%";style.top=-top+"%";style.width=(2*left+100)+"%";style.height=(2*top+100)+"%";}
+style.visibility="hidden";style.opacity=0;if(this.layer.opacity<1){style.filter='alpha(opacity='+
+(this.layer.opacity*100)+')';}
+style.position="absolute";if(this.layerAlphaHack){style.paddingTop=style.height;style.height="0";style.width="100%";}
+if(this.frame){this.frame.appendChild(this.imgDiv);}}
+return this.imgDiv;},initImage:function(){this.events.triggerEvent(this._loadEvent);var img=this.getImage();if(this.url&&img.getAttribute("src")==this.url){this.onImageLoad();}else{var load=OpenLayers.Function.bind(function(){OpenLayers.Event.stopObservingElement(img);OpenLayers.Event.observe(img,"load",OpenLayers.Function.bind(this.onImageLoad,this));OpenLayers.Event.observe(img,"error",OpenLayers.Function.bind(this.onImageError,this));this.imageReloadAttempts=0;this.setImgSrc(this.url);},this);if(img.getAttribute("src")==this.blankImageUrl){load();}else{OpenLayers.Event.observe(img,"load",load);OpenLayers.Event.observe(img,"error",load);if(this.crossOriginKeyword){img.removeAttribute("crossorigin");}
+img.src=this.blankImageUrl;}}},setImgSrc:function(url){var img=this.imgDiv;img.style.visibility='hidden';img.style.opacity=0;if(url){if(this.crossOriginKeyword){if(url.substr(0,5)!=='data:'){img.setAttribute("crossorigin",this.crossOriginKeyword);}else{img.removeAttribute("crossorigin");}}
+img.src=url;}},getTile:function(){return this.frame?this.frame:this.getImage();},createBackBuffer:function(){if(!this.imgDiv||this.isLoading){return;}
+var backBuffer;if(this.frame){backBuffer=this.frame.cloneNode(false);backBuffer.appendChild(this.imgDiv);}else{backBuffer=this.imgDiv;}
+this.imgDiv=null;return backBuffer;},onImageLoad:function(){var img=this.imgDiv;OpenLayers.Event.stopObservingElement(img);img.style.visibility='inherit';img.style.opacity=this.layer.opacity;this.isLoading=false;this.canvasContext=null;this.events.triggerEvent("loadend");if(parseFloat(navigator.appVersion.split("MSIE")[1])<7&&this.layer&&this.layer.div){var span=document.createElement("span");span.style.display="none";var layerDiv=this.layer.div;layerDiv.appendChild(span);window.setTimeout(function(){span.parentNode===layerDiv&&span.parentNode.removeChild(span);},0);}
+if(this.layerAlphaHack===true){img.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+
+img.src+"', sizingMethod='scale')";}},onImageError:function(){var img=this.imgDiv;if(img.src!=null){this.imageReloadAttempts++;if(this.imageReloadAttempts<=OpenLayers.IMAGE_RELOAD_ATTEMPTS){this.setImgSrc(this.layer.getURL(this.bounds));}else{OpenLayers.Element.addClass(img,"olImageLoadError");this.events.triggerEvent("loaderror");this.onImageLoad();}}},getCanvasContext:function(){if(OpenLayers.CANVAS_SUPPORTED&&this.imgDiv&&!this.isLoading){if(!this.canvasContext){var canvas=document.createElement("canvas");canvas.width=this.size.w;canvas.height=this.size.h;this.canvasContext=canvas.getContext("2d");this.canvasContext.drawImage(this.imgDiv,0,0);}
+return this.canvasContext;}},CLASS_NAME:"OpenLayers.Tile.Image"});OpenLayers.Layer.Grid=OpenLayers.Class(OpenLayers.Layer.HTTPRequest,{tileSize:null,tileOriginCorner:"bl",tileOrigin:null,tileOptions:null,tileClass:OpenLayers.Tile.Image,grid:null,singleTile:false,ratio:1.5,buffer:0,transitionEffect:null,numLoadingTiles:0,tileLoadingDelay:85,serverResolutions:null,moveTimerId:null,deferMoveGriddedTiles:null,tileQueueId:null,tileQueue:null,loading:false,backBuffer:null,gridResolution:null,backBufferResolution:null,backBufferLonLat:null,backBufferTimerId:null,removeBackBufferDelay:null,className:null,initialize:function(name,url,params,options){OpenLayers.Layer.HTTPRequest.prototype.initialize.apply(this,arguments);this.grid=[];this.tileQueue=[];if(this.removeBackBufferDelay===null){this.removeBackBufferDelay=this.singleTile?0:2500;}
+if(this.className===null){this.className=this.singleTile?'olLayerGridSingleTile':'olLayerGrid';}
+if(!OpenLayers.Animation.isNative){this.deferMoveGriddedTiles=OpenLayers.Function.bind(function(){this.moveGriddedTiles(true);this.moveTimerId=null;},this);}},setMap:function(map){OpenLayers.Layer.HTTPRequest.prototype.setMap.call(this,map);OpenLayers.Element.addClass(this.div,this.className);},removeMap:function(map){if(this.moveTimerId!==null){window.clearTimeout(this.moveTimerId);this.moveTimerId=null;}
+this.clearTileQueue();if(this.backBufferTimerId!==null){window.clearTimeout(this.backBufferTimerId);this.backBufferTimerId=null;}},destroy:function(){this.removeBackBuffer();this.clearGrid();this.grid=null;this.tileSize=null;OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this,arguments);},clearGrid:function(){this.clearTileQueue();if(this.grid){for(var iRow=0,len=this.grid.length;iRow<len;iRow++){var row=this.grid[iRow];for(var iCol=0,clen=row.length;iCol<clen;iCol++){var tile=row[iCol];this.destroyTile(tile);}}
+this.grid=[];this.gridResolution=null;}},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Grid(this.name,this.url,this.params,this.getOptions());}
+obj=OpenLayers.Layer.HTTPRequest.prototype.clone.apply(this,[obj]);if(this.tileSize!=null){obj.tileSize=this.tileSize.clone();}
+obj.grid=[];obj.gridResolution=null;obj.backBuffer=null;obj.backBufferTimerId=null;obj.tileQueue=[];obj.tileQueueId=null;obj.loading=false;obj.moveTimerId=null;return obj;},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.HTTPRequest.prototype.moveTo.apply(this,arguments);bounds=bounds||this.map.getExtent();if(bounds!=null){var forceReTile=!this.grid.length||zoomChanged;var tilesBounds=this.getTilesBounds();var resolution=this.map.getResolution();var serverResolution=this.getServerResolution(resolution);if(this.singleTile){if(forceReTile||(!dragging&&!tilesBounds.containsBounds(bounds))){if(zoomChanged&&this.transitionEffect!=='resize'){this.removeBackBuffer();}
+if(!zoomChanged||this.transitionEffect==='resize'){this.applyBackBuffer(serverResolution);}
+this.initSingleTile(bounds);}}else{forceReTile=forceReTile||!tilesBounds.intersectsBounds(bounds,{worldBounds:this.map.baseLayer.wrapDateLine&&this.map.getMaxExtent()});if(resolution!==serverResolution){bounds=this.map.calculateBounds(null,serverResolution);if(forceReTile){var scale=serverResolution/resolution;this.transformDiv(scale);}}else{this.div.style.width='100%';this.div.style.height='100%';this.div.style.left='0%';this.div.style.top='0%';}
+if(forceReTile){if(zoomChanged&&this.transitionEffect==='resize'){this.applyBackBuffer(serverResolution);}
+this.initGriddedTiles(bounds);}else{this.moveGriddedTiles();}}}},getTileData:function(loc){var data=null,x=loc.lon,y=loc.lat,numRows=this.grid.length;if(this.map&&numRows){var res=this.map.getResolution(),tileWidth=this.tileSize.w,tileHeight=this.tileSize.h,bounds=this.grid[0][0].bounds,left=bounds.left,top=bounds.top;if(x<left){if(this.map.baseLayer.wrapDateLine){var worldWidth=this.map.getMaxExtent().getWidth();var worldsAway=Math.ceil((left-x)/worldWidth);x+=worldWidth*worldsAway;}}
+var dtx=(x-left)/(res*tileWidth);var dty=(top-y)/(res*tileHeight);var col=Math.floor(dtx);var row=Math.floor(dty);if(row>=0&&row<numRows){var tile=this.grid[row][col];if(tile){data={tile:tile,i:Math.floor((dtx-col)*tileWidth),j:Math.floor((dty-row)*tileHeight)};}}}
+return data;},queueTileDraw:function(evt){var tile=evt.object;if(!~OpenLayers.Util.indexOf(this.tileQueue,tile)){this.tileQueue.push(tile);}
+if(!this.tileQueueId){this.tileQueueId=OpenLayers.Animation.start(OpenLayers.Function.bind(this.drawTileFromQueue,this),null,this.div);}
+return false;},drawTileFromQueue:function(){if(this.tileQueue.length===0){this.clearTileQueue();}else{this.tileQueue.shift().draw(true);}},clearTileQueue:function(){OpenLayers.Animation.stop(this.tileQueueId);this.tileQueueId=null;this.tileQueue=[];},destroyTile:function(tile){this.removeTileMonitoringHooks(tile);tile.destroy();},getServerResolution:function(resolution){resolution=resolution||this.map.getResolution();if(this.serverResolutions&&OpenLayers.Util.indexOf(this.serverResolutions,resolution)===-1){var i,serverResolution;for(i=this.serverResolutions.length-1;i>=0;i--){serverResolution=this.serverResolutions[i];if(serverResolution>resolution){resolution=serverResolution;break;}}
+if(i===-1){throw'no appropriate resolution in serverResolutions';}}
+return resolution;},getServerZoom:function(){var resolution=this.getServerResolution();return this.serverResolutions?OpenLayers.Util.indexOf(this.serverResolutions,resolution):this.map.getZoomForResolution(resolution)+(this.zoomOffset||0);},transformDiv:function(scale){this.div.style.width=100*scale+'%';this.div.style.height=100*scale+'%';var size=this.map.getSize();var lcX=parseInt(this.map.layerContainerDiv.style.left,10);var lcY=parseInt(this.map.layerContainerDiv.style.top,10);var x=(lcX-(size.w/2.0))*(scale-1);var y=(lcY-(size.h/2.0))*(scale-1);this.div.style.left=x+'%';this.div.style.top=y+'%';},getResolutionScale:function(){return parseInt(this.div.style.width,10)/100;},applyBackBuffer:function(resolution){if(this.backBufferTimerId!==null){this.removeBackBuffer();}
+var backBuffer=this.backBuffer;if(!backBuffer){backBuffer=this.createBackBuffer();if(!backBuffer){return;}
+this.div.insertBefore(backBuffer,this.div.firstChild);this.backBuffer=backBuffer;var topLeftTileBounds=this.grid[0][0].bounds;this.backBufferLonLat={lon:topLeftTileBounds.left,lat:topLeftTileBounds.top};this.backBufferResolution=this.gridResolution;}
+var style=backBuffer.style;var ratio=this.backBufferResolution/resolution;style.width=100*ratio+'%';style.height=100*ratio+'%';var position=this.getViewPortPxFromLonLat(this.backBufferLonLat,resolution);var leftOffset=parseInt(this.map.layerContainerDiv.style.left,10);var topOffset=parseInt(this.map.layerContainerDiv.style.top,10);backBuffer.style.left=Math.round(position.x-leftOffset)+'%';backBuffer.style.top=Math.round(position.y-topOffset)+'%';},createBackBuffer:function(){var backBuffer;if(this.grid.length>0){backBuffer=document.createElement('div');backBuffer.id=this.div.id+'_bb';backBuffer.className='olBackBuffer';backBuffer.style.position='absolute';backBuffer.style.width='100%';backBuffer.style.height='100%';for(var i=0,lenI=this.grid.length;i<lenI;i++){for(var j=0,lenJ=this.grid[i].length;j<lenJ;j++){var tile=this.grid[i][j].createBackBuffer();if(!tile){continue;}
+tile.style.top=(i*this.tileSize.h)+'%';tile.style.left=(j*this.tileSize.w)+'%';backBuffer.appendChild(tile);}}}
+return backBuffer;},removeBackBuffer:function(){if(this.backBuffer){this.div.removeChild(this.backBuffer);this.backBuffer=null;this.backBufferResolution=null;if(this.backBufferTimerId!==null){window.clearTimeout(this.backBufferTimerId);this.backBufferTimerId=null;}}},moveByPx:function(dx,dy){if(!this.singleTile){this.moveGriddedTiles();}},setTileSize:function(size){if(this.singleTile){size=this.map.getSize();size.h=parseInt(size.h*this.ratio);size.w=parseInt(size.w*this.ratio);}
+OpenLayers.Layer.HTTPRequest.prototype.setTileSize.apply(this,[size]);},getTilesBounds:function(){var bounds=null;var length=this.grid.length;if(length){var bottomLeftTileBounds=this.grid[length-1][0].bounds,width=this.grid[0].length*bottomLeftTileBounds.getWidth(),height=this.grid.length*bottomLeftTileBounds.getHeight();bounds=new OpenLayers.Bounds(bottomLeftTileBounds.left,bottomLeftTileBounds.bottom,bottomLeftTileBounds.left+width,bottomLeftTileBounds.bottom+height);}
+return bounds;},initSingleTile:function(bounds){this.clearTileQueue();var center=bounds.getCenterLonLat();var tileWidth=bounds.getWidth()*this.ratio;var tileHeight=bounds.getHeight()*this.ratio;var tileBounds=new OpenLayers.Bounds(center.lon-(tileWidth/2),center.lat-(tileHeight/2),center.lon+(tileWidth/2),center.lat+(tileHeight/2));var px=this.map.getLayerPxFromLonLat({lon:tileBounds.left,lat:tileBounds.top});if(!this.grid.length){this.grid[0]=[];}
+var tile=this.grid[0][0];if(!tile){tile=this.addTile(tileBounds,px);this.addTileMonitoringHooks(tile);tile.draw();this.grid[0][0]=tile;}else{tile.moveTo(tileBounds,px);}
+this.removeExcessTiles(1,1);this.gridResolution=this.getServerResolution();},calculateGridLayout:function(bounds,origin,resolution){var tilelon=resolution*this.tileSize.w;var tilelat=resolution*this.tileSize.h;var offsetlon=bounds.left-origin.lon;var tilecol=Math.floor(offsetlon/tilelon)-this.buffer;var tilecolremain=offsetlon/tilelon-tilecol;var tileoffsetx=-tilecolremain*this.tileSize.w;var tileoffsetlon=origin.lon+tilecol*tilelon;var offsetlat=bounds.top-(origin.lat+tilelat);var tilerow=Math.ceil(offsetlat/tilelat)+this.buffer;var tilerowremain=tilerow-offsetlat/tilelat;var tileoffsety=-tilerowremain*this.tileSize.h;var tileoffsetlat=origin.lat+tilerow*tilelat;return{tilelon:tilelon,tilelat:tilelat,tileoffsetlon:tileoffsetlon,tileoffsetlat:tileoffsetlat,tileoffsetx:tileoffsetx,tileoffsety:tileoffsety};},getTileOrigin:function(){var origin=this.tileOrigin;if(!origin){var extent=this.getMaxExtent();var edges=({"tl":["left","top"],"tr":["right","top"],"bl":["left","bottom"],"br":["right","bottom"]})[this.tileOriginCorner];origin=new OpenLayers.LonLat(extent[edges[0]],extent[edges[1]]);}
+return origin;},initGriddedTiles:function(bounds){this.clearTileQueue();var viewSize=this.map.getSize();var minRows=Math.ceil(viewSize.h/this.tileSize.h)+
+Math.max(1,2*this.buffer);var minCols=Math.ceil(viewSize.w/this.tileSize.w)+
+Math.max(1,2*this.buffer);var origin=this.getTileOrigin();var resolution=this.getServerResolution();var tileLayout=this.calculateGridLayout(bounds,origin,resolution);var tileoffsetx=Math.round(tileLayout.tileoffsetx);var tileoffsety=Math.round(tileLayout.tileoffsety);var tileoffsetlon=tileLayout.tileoffsetlon;var tileoffsetlat=tileLayout.tileoffsetlat;var tilelon=tileLayout.tilelon;var tilelat=tileLayout.tilelat;var startX=tileoffsetx;var startLon=tileoffsetlon;var rowidx=0;var layerContainerDivLeft=parseInt(this.map.layerContainerDiv.style.left);var layerContainerDivTop=parseInt(this.map.layerContainerDiv.style.top);var tileData=[],center=this.map.getCenter();do{var row=this.grid[rowidx++];if(!row){row=[];this.grid.push(row);}
+tileoffsetlon=startLon;tileoffsetx=startX;var colidx=0;do{var tileBounds=new OpenLayers.Bounds(tileoffsetlon,tileoffsetlat,tileoffsetlon+tilelon,tileoffsetlat+tilelat);var x=tileoffsetx;x-=layerContainerDivLeft;var y=tileoffsety;y-=layerContainerDivTop;var px=new OpenLayers.Pixel(x,y);var tile=row[colidx++];if(!tile){tile=this.addTile(tileBounds,px);this.addTileMonitoringHooks(tile);row.push(tile);}else{tile.moveTo(tileBounds,px,false);}
+var tileCenter=tileBounds.getCenterLonLat();tileData.push({tile:tile,distance:Math.pow(tileCenter.lon-center.lon,2)+
+Math.pow(tileCenter.lat-center.lat,2)});tileoffsetlon+=tilelon;tileoffsetx+=this.tileSize.w;}while((tileoffsetlon<=bounds.right+tilelon*this.buffer)||colidx<minCols);tileoffsetlat-=tilelat;tileoffsety+=this.tileSize.h;}while((tileoffsetlat>=bounds.bottom-tilelat*this.buffer)||rowidx<minRows);this.removeExcessTiles(rowidx,colidx);this.gridResolution=this.getServerResolution();tileData.sort(function(a,b){return a.distance-b.distance;});for(var i=0,ii=tileData.length;i<ii;++i){tileData[i].tile.draw();}},getMaxExtent:function(){return this.maxExtent;},addTile:function(bounds,position){var tile=new this.tileClass(this,position,bounds,null,this.tileSize,this.tileOptions);tile.events.register("beforedraw",this,this.queueTileDraw);return tile;},addTileMonitoringHooks:function(tile){tile.onLoadStart=function(){if(this.loading===false){this.loading=true;this.events.triggerEvent("loadstart");}
+this.events.triggerEvent("tileloadstart",{tile:tile});this.numLoadingTiles++;};tile.onLoadEnd=function(){this.numLoadingTiles--;this.events.triggerEvent("tileloaded",{tile:tile});if(this.tileQueue.length===0&&this.numLoadingTiles===0){this.loading=false;this.events.triggerEvent("loadend");if(this.backBuffer){this.backBufferTimerId=window.setTimeout(OpenLayers.Function.bind(this.removeBackBuffer,this),this.removeBackBufferDelay);}}};tile.onLoadError=function(){this.events.triggerEvent("tileerror",{tile:tile});};tile.events.on({"loadstart":tile.onLoadStart,"loadend":tile.onLoadEnd,"unload":tile.onLoadEnd,"loaderror":tile.onLoadError,scope:this});},removeTileMonitoringHooks:function(tile){tile.unload();tile.events.un({"loadstart":tile.onLoadStart,"loadend":tile.onLoadEnd,"unload":tile.onLoadEnd,"loaderror":tile.onLoadError,scope:this});},moveGriddedTiles:function(deferred){if(!deferred&&!OpenLayers.Animation.isNative){if(this.moveTimerId!=null){window.clearTimeout(this.moveTimerId);}
+this.moveTimerId=window.setTimeout(this.deferMoveGriddedTiles,this.tileLoadingDelay);return;}
+var buffer=this.buffer||1;var scale=this.getResolutionScale();while(true){var tlViewPort={x:(this.grid[0][0].position.x*scale)+
+parseInt(this.div.style.left,10)+
+parseInt(this.map.layerContainerDiv.style.left),y:(this.grid[0][0].position.y*scale)+
+parseInt(this.div.style.top,10)+
+parseInt(this.map.layerContainerDiv.style.top)};var tileSize={w:this.tileSize.w*scale,h:this.tileSize.h*scale};if(tlViewPort.x>-tileSize.w*(buffer-1)){this.shiftColumn(true);}else if(tlViewPort.x<-tileSize.w*buffer){this.shiftColumn(false);}else if(tlViewPort.y>-tileSize.h*(buffer-1)){this.shiftRow(true);}else if(tlViewPort.y<-tileSize.h*buffer){this.shiftRow(false);}else{break;}}},shiftRow:function(prepend){var modelRowIndex=(prepend)?0:(this.grid.length-1);var grid=this.grid;var modelRow=grid[modelRowIndex];var resolution=this.getServerResolution();var deltaY=(prepend)?-this.tileSize.h:this.tileSize.h;var deltaLat=resolution*-deltaY;var row=(prepend)?grid.pop():grid.shift();for(var i=0,len=modelRow.length;i<len;i++){var modelTile=modelRow[i];var bounds=modelTile.bounds.clone();var position=modelTile.position.clone();bounds.bottom=bounds.bottom+deltaLat;bounds.top=bounds.top+deltaLat;position.y=position.y+deltaY;row[i].moveTo(bounds,position);}
+if(prepend){grid.unshift(row);}else{grid.push(row);}},shiftColumn:function(prepend){var deltaX=(prepend)?-this.tileSize.w:this.tileSize.w;var resolution=this.getServerResolution();var deltaLon=resolution*deltaX;for(var i=0,len=this.grid.length;i<len;i++){var row=this.grid[i];var modelTileIndex=(prepend)?0:(row.length-1);var modelTile=row[modelTileIndex];var bounds=modelTile.bounds.clone();var position=modelTile.position.clone();bounds.left=bounds.left+deltaLon;bounds.right=bounds.right+deltaLon;position.x=position.x+deltaX;var tile=prepend?this.grid[i].pop():this.grid[i].shift();tile.moveTo(bounds,position);if(prepend){row.unshift(tile);}else{row.push(tile);}}},removeExcessTiles:function(rows,columns){var i,l;while(this.grid.length>rows){var row=this.grid.pop();for(i=0,l=row.length;i<l;i++){var tile=row[i];this.destroyTile(tile);}}
+for(i=0,l=this.grid.length;i<l;i++){while(this.grid[i].length>columns){var row=this.grid[i];var tile=row.pop();this.destroyTile(tile);}}},onMapResize:function(){if(this.singleTile){this.clearGrid();this.setTileSize();}},getTileBounds:function(viewPortPx){var maxExtent=this.maxExtent;var resolution=this.getResolution();var tileMapWidth=resolution*this.tileSize.w;var tileMapHeight=resolution*this.tileSize.h;var mapPoint=this.getLonLatFromViewPortPx(viewPortPx);var tileLeft=maxExtent.left+(tileMapWidth*Math.floor((mapPoint.lon-
+maxExtent.left)/tileMapWidth));var tileBottom=maxExtent.bottom+(tileMapHeight*Math.floor((mapPoint.lat-
+maxExtent.bottom)/tileMapHeight));return new OpenLayers.Bounds(tileLeft,tileBottom,tileLeft+tileMapWidth,tileBottom+tileMapHeight);},CLASS_NAME:"OpenLayers.Layer.Grid"});OpenLayers.Layer.XYZ=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,sphericalMercator:false,zoomOffset:0,serverResolutions:null,initialize:function(name,url,options){if(options&&options.sphericalMercator||this.sphericalMercator){options=OpenLayers.Util.extend({projection:"EPSG:900913",numZoomLevels:19},options);}
+OpenLayers.Layer.Grid.prototype.initialize.apply(this,[name||this.name,url||this.url,{},options]);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.XYZ(this.name,this.url,this.getOptions());}
+obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){var xyz=this.getXYZ(bounds);var url=this.url;if(OpenLayers.Util.isArray(url)){var s=''+xyz.x+xyz.y+xyz.z;url=this.selectUrl(s,url);}
+return OpenLayers.String.format(url,xyz);},getXYZ:function(bounds){var res=this.getServerResolution();var x=Math.round((bounds.left-this.maxExtent.left)/(res*this.tileSize.w));var y=Math.round((this.maxExtent.top-bounds.top)/(res*this.tileSize.h));var z=this.getServerZoom();if(this.wrapDateLine){var limit=Math.pow(2,z);x=((x%limit)+limit)%limit;}
+return{'x':x,'y':y,'z':z};},setMap:function(map){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);if(!this.tileOrigin){this.tileOrigin=new OpenLayers.LonLat(this.maxExtent.left,this.maxExtent.bottom);}},CLASS_NAME:"OpenLayers.Layer.XYZ"});OpenLayers.Layer.OSM=OpenLayers.Class(OpenLayers.Layer.XYZ,{name:"OpenStreetMap",url:['http://a.tile.openstreetmap.org/${z}/${x}/${y}.png','http://b.tile.openstreetmap.org/${z}/${x}/${y}.png','http://c.tile.openstreetmap.org/${z}/${x}/${y}.png'],attribution:"Data CC-By-SA by <a href='http://openstreetmap.org/'>OpenStreetMap</a>",sphericalMercator:true,wrapDateLine:true,tileOptions:null,initialize:function(name,url,options){OpenLayers.Layer.XYZ.prototype.initialize.apply(this,arguments);this.tileOptions=OpenLayers.Util.extend({crossOriginKeyword:'anonymous'},this.options&&this.options.tileOptions);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.OSM(this.name,this.url,this.getOptions());}
+obj=OpenLayers.Layer.XYZ.prototype.clone.apply(this,[obj]);return obj;},CLASS_NAME:"OpenLayers.Layer.OSM"});OpenLayers.Renderer=OpenLayers.Class({container:null,root:null,extent:null,locked:false,size:null,resolution:null,map:null,featureDx:0,initialize:function(containerID,options){this.container=OpenLayers.Util.getElement(containerID);OpenLayers.Util.extend(this,options);},destroy:function(){this.container=null;this.extent=null;this.size=null;this.resolution=null;this.map=null;},supported:function(){return false;},setExtent:function(extent,resolutionChanged){this.extent=extent.clone();if(this.map.baseLayer&&this.map.baseLayer.wrapDateLine){var ratio=extent.getWidth()/this.map.getExtent().getWidth(),extent=extent.scale(1/ratio);this.extent=extent.wrapDateLine(this.map.getMaxExtent()).scale(ratio);}
+if(resolutionChanged){this.resolution=null;}
+return true;},setSize:function(size){this.size=size.clone();this.resolution=null;},getResolution:function(){this.resolution=this.resolution||this.map.getResolution();return this.resolution;},drawFeature:function(feature,style){if(style==null){style=feature.style;}
+if(feature.geometry){var bounds=feature.geometry.getBounds();if(bounds){var worldBounds;if(this.map.baseLayer&&this.map.baseLayer.wrapDateLine){worldBounds=this.map.getMaxExtent();}
+if(!bounds.intersectsBounds(this.extent,{worldBounds:worldBounds})){style={display:"none"};}else{this.calculateFeatureDx(bounds,worldBounds);}
+var rendered=this.drawGeometry(feature.geometry,style,feature.id);if(style.display!="none"&&style.label&&rendered!==false){var location=feature.geometry.getCentroid();if(style.labelXOffset||style.labelYOffset){var xOffset=isNaN(style.labelXOffset)?0:style.labelXOffset;var yOffset=isNaN(style.labelYOffset)?0:style.labelYOffset;var res=this.getResolution();location.move(xOffset*res,yOffset*res);}
+this.drawText(feature.id,style,location);}else{this.removeText(feature.id);}
+return rendered;}}},calculateFeatureDx:function(bounds,worldBounds){this.featureDx=0;if(worldBounds){var worldWidth=worldBounds.getWidth(),rendererCenterX=(this.extent.left+this.extent.right)/2,featureCenterX=(bounds.left+bounds.right)/2,worldsAway=Math.round((featureCenterX-rendererCenterX)/worldWidth);this.featureDx=worldsAway*worldWidth;}},drawGeometry:function(geometry,style,featureId){},drawText:function(featureId,style,location){},removeText:function(featureId){},clear:function(){},getFeatureIdFromEvent:function(evt){},eraseFeatures:function(features){if(!(OpenLayers.Util.isArray(features))){features=[features];}
+for(var i=0,len=features.length;i<len;++i){var feature=features[i];this.eraseGeometry(feature.geometry,feature.id);this.removeText(feature.id);}},eraseGeometry:function(geometry,featureId){},moveRoot:function(renderer){},getRenderLayerId:function(){return this.container.id;},applyDefaultSymbolizer:function(symbolizer){var result=OpenLayers.Util.extend({},OpenLayers.Renderer.defaultSymbolizer);if(symbolizer.stroke===false){delete result.strokeWidth;delete result.strokeColor;}
+if(symbolizer.fill===false){delete result.fillColor;}
+OpenLayers.Util.extend(result,symbolizer);return result;},CLASS_NAME:"OpenLayers.Renderer"});OpenLayers.Renderer.defaultSymbolizer={fillColor:"#000000",strokeColor:"#000000",strokeWidth:2,fillOpacity:1,strokeOpacity:1,pointRadius:0,labelAlign:'cm'};OpenLayers.Renderer.symbol={"star":[350,75,379,161,469,161,397,215,423,301,350,250,277,301,303,215,231,161,321,161,350,75],"cross":[4,0,6,0,6,4,10,4,10,6,6,6,6,10,4,10,4,6,0,6,0,4,4,4,4,0],"x":[0,0,25,0,50,35,75,0,100,0,65,50,100,100,75,100,50,65,25,100,0,100,35,50,0,0],"square":[0,0,0,1,1,1,1,0,0,0],"triangle":[0,10,10,10,5,0,0,10]};OpenLayers.Renderer.Canvas=OpenLayers.Class(OpenLayers.Renderer,{hitDetection:true,hitOverflow:0,canvas:null,features:null,pendingRedraw:false,cachedSymbolBounds:{},initialize:function(containerID,options){OpenLayers.Renderer.prototype.initialize.apply(this,arguments);this.root=document.createElement("canvas");this.container.appendChild(this.root);this.canvas=this.root.getContext("2d");this.features={};if(this.hitDetection){this.hitCanvas=document.createElement("canvas");this.hitContext=this.hitCanvas.getContext("2d");}},setExtent:function(){OpenLayers.Renderer.prototype.setExtent.apply(this,arguments);return false;},eraseGeometry:function(geometry,featureId){this.eraseFeatures(this.features[featureId][0]);},supported:function(){return OpenLayers.CANVAS_SUPPORTED;},setSize:function(size){this.size=size.clone();var root=this.root;root.style.width=size.w+"px";root.style.height=size.h+"px";root.width=size.w;root.height=size.h;this.resolution=null;if(this.hitDetection){var hitCanvas=this.hitCanvas;hitCanvas.style.width=size.w+"px";hitCanvas.style.height=size.h+"px";hitCanvas.width=size.w;hitCanvas.height=size.h;}},drawFeature:function(feature,style){var rendered;if(feature.geometry){style=this.applyDefaultSymbolizer(style||feature.style);var bounds=feature.geometry.getBounds();var worldBounds;if(this.map.baseLayer&&this.map.baseLayer.wrapDateLine){worldBounds=this.map.getMaxExtent();}
+var intersects=bounds&&bounds.intersectsBounds(this.extent,{worldBounds:worldBounds});rendered=(style.display!=="none")&&!!bounds&&intersects;if(rendered){this.features[feature.id]=[feature,style];}
+else{delete(this.features[feature.id]);}
+this.pendingRedraw=true;}
+if(this.pendingRedraw&&!this.locked){this.redraw();this.pendingRedraw=false;}
+return rendered;},drawGeometry:function(geometry,style,featureId){var className=geometry.CLASS_NAME;if((className=="OpenLayers.Geometry.Collection")||(className=="OpenLayers.Geometry.MultiPoint")||(className=="OpenLayers.Geometry.MultiLineString")||(className=="OpenLayers.Geometry.MultiPolygon")){for(var i=0;i<geometry.components.length;i++){this.drawGeometry(geometry.components[i],style,featureId);}
+return;}
+switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":this.drawPoint(geometry,style,featureId);break;case"OpenLayers.Geometry.LineString":this.drawLineString(geometry,style,featureId);break;case"OpenLayers.Geometry.LinearRing":this.drawLinearRing(geometry,style,featureId);break;case"OpenLayers.Geometry.Polygon":this.drawPolygon(geometry,style,featureId);break;default:break;}},drawExternalGraphic:function(geometry,style,featureId){var img=new Image();if(style.graphicTitle){img.title=style.graphicTitle;}
+var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset:-(0.5*height);var opacity=style.graphicOpacity||style.fillOpacity;var onLoad=function(){if(!this.features[featureId]){return;}
+var pt=this.getLocalXY(geometry);var p0=pt[0];var p1=pt[1];if(!isNaN(p0)&&!isNaN(p1)){var x=(p0+xOffset)|0;var y=(p1+yOffset)|0;var canvas=this.canvas;canvas.globalAlpha=opacity;var factor=OpenLayers.Renderer.Canvas.drawImageScaleFactor||(OpenLayers.Renderer.Canvas.drawImageScaleFactor=/android 2.1/.test(navigator.userAgent.toLowerCase())?320/window.screen.width:1);canvas.drawImage(img,x*factor,y*factor,width*factor,height*factor);if(this.hitDetection){this.setHitContextStyle("fill",featureId);this.hitContext.fillRect(x,y,width,height);}}};img.onload=OpenLayers.Function.bind(onLoad,this);img.src=style.externalGraphic;},drawNamedSymbol:function(geometry,style,featureId){var x,y,cx,cy,i,symbolBounds,scaling,angle;var unscaledStrokeWidth;var deg2rad=Math.PI/180.0;var symbol=OpenLayers.Renderer.symbol[style.graphicName];if(!symbol){throw new Error(style.graphicName+' is not a valid symbol name');}
+if(!symbol.length||symbol.length<2)return;var pt=this.getLocalXY(geometry);var p0=pt[0];var p1=pt[1];if(isNaN(p0)||isNaN(p1))return;this.canvas.lineCap="round";this.canvas.lineJoin="round";if(this.hitDetection){this.hitContext.lineCap="round";this.hitContext.lineJoin="round";}
+if(style.graphicName in this.cachedSymbolBounds){symbolBounds=this.cachedSymbolBounds[style.graphicName];}else{symbolBounds=new OpenLayers.Bounds();for(i=0;i<symbol.length;i+=2){symbolBounds.extend(new OpenLayers.LonLat(symbol[i],symbol[i+1]));}
+this.cachedSymbolBounds[style.graphicName]=symbolBounds;}
+this.canvas.save();if(this.hitDetection){this.hitContext.save();}
+this.canvas.translate(p0,p1);if(this.hitDetection){this.hitContext.translate(p0,p1);}
+angle=deg2rad*style.rotation;if(!isNaN(angle)){this.canvas.rotate(angle);if(this.hitDetection){this.hitContext.rotate(angle);}}
+scaling=2.0*style.pointRadius/Math.max(symbolBounds.getWidth(),symbolBounds.getHeight());this.canvas.scale(scaling,scaling);if(this.hitDetection){this.hitContext.scale(scaling,scaling);}
+cx=symbolBounds.getCenterLonLat().lon;cy=symbolBounds.getCenterLonLat().lat;this.canvas.translate(-cx,-cy);if(this.hitDetection){this.hitContext.translate(-cx,-cy);}
+unscaledStrokeWidth=style.strokeWidth;style.strokeWidth=unscaledStrokeWidth/scaling;if(style.fill!==false){this.setCanvasStyle("fill",style);this.canvas.beginPath();for(i=0;i<symbol.length;i=i+2){x=symbol[i];y=symbol[i+1];if(i==0)this.canvas.moveTo(x,y);this.canvas.lineTo(x,y);}
+this.canvas.closePath();this.canvas.fill();if(this.hitDetection){this.setHitContextStyle("fill",featureId,style);this.hitContext.beginPath();for(i=0;i<symbol.length;i=i+2){x=symbol[i];y=symbol[i+1];if(i==0)this.canvas.moveTo(x,y);this.hitContext.lineTo(x,y);}
+this.hitContext.closePath();this.hitContext.fill();}}
+if(style.stroke!==false){this.setCanvasStyle("stroke",style);this.canvas.beginPath();for(i=0;i<symbol.length;i=i+2){x=symbol[i];y=symbol[i+1];if(i==0)this.canvas.moveTo(x,y);this.canvas.lineTo(x,y);}
+this.canvas.closePath();this.canvas.stroke();if(this.hitDetection){this.setHitContextStyle("stroke",featureId,style,scaling);this.hitContext.beginPath();for(i=0;i<symbol.length;i=i+2){x=symbol[i];y=symbol[i+1];if(i==0)this.hitContext.moveTo(x,y);this.hitContext.lineTo(x,y);}
+this.hitContext.closePath();this.hitContext.stroke();}}
+style.strokeWidth=unscaledStrokeWidth;this.canvas.restore();if(this.hitDetection){this.hitContext.restore();}
+this.setCanvasStyle("reset");},setCanvasStyle:function(type,style){if(type==="fill"){this.canvas.globalAlpha=style['fillOpacity'];this.canvas.fillStyle=style['fillColor'];}else if(type==="stroke"){this.canvas.globalAlpha=style['strokeOpacity'];this.canvas.strokeStyle=style['strokeColor'];this.canvas.lineWidth=style['strokeWidth'];}else{this.canvas.globalAlpha=0;this.canvas.lineWidth=1;}},featureIdToHex:function(featureId){var id=Number(featureId.split("_").pop())+1;if(id>=16777216){this.hitOverflow=id-16777215;id=id%16777216+1;}
+var hex="000000"+id.toString(16);var len=hex.length;hex="#"+hex.substring(len-6,len);return hex;},setHitContextStyle:function(type,featureId,symbolizer,strokeScaling){var hex=this.featureIdToHex(featureId);if(type=="fill"){this.hitContext.globalAlpha=1.0;this.hitContext.fillStyle=hex;}else if(type=="stroke"){this.hitContext.globalAlpha=1.0;this.hitContext.strokeStyle=hex;if(typeof strokeScaling==="undefined"){this.hitContext.lineWidth=symbolizer.strokeWidth+2;}else{if(!isNaN(strokeScaling)){this.hitContext.lineWidth=symbolizer.strokeWidth+2.0/strokeScaling;}}}else{this.hitContext.globalAlpha=0;this.hitContext.lineWidth=1;}},drawPoint:function(geometry,style,featureId){if(style.graphic!==false){if(style.externalGraphic){this.drawExternalGraphic(geometry,style,featureId);}else if(style.graphicName&&(style.graphicName!="circle")){this.drawNamedSymbol(geometry,style,featureId);}else{var pt=this.getLocalXY(geometry);var p0=pt[0];var p1=pt[1];if(!isNaN(p0)&&!isNaN(p1)){var twoPi=Math.PI*2;var radius=style.pointRadius;if(style.fill!==false){this.setCanvasStyle("fill",style);this.canvas.beginPath();this.canvas.arc(p0,p1,radius,0,twoPi,true);this.canvas.fill();if(this.hitDetection){this.setHitContextStyle("fill",featureId,style);this.hitContext.beginPath();this.hitContext.arc(p0,p1,radius,0,twoPi,true);this.hitContext.fill();}}
+if(style.stroke!==false){this.setCanvasStyle("stroke",style);this.canvas.beginPath();this.canvas.arc(p0,p1,radius,0,twoPi,true);this.canvas.stroke();if(this.hitDetection){this.setHitContextStyle("stroke",featureId,style);this.hitContext.beginPath();this.hitContext.arc(p0,p1,radius,0,twoPi,true);this.hitContext.stroke();}
+this.setCanvasStyle("reset");}}}}},drawLineString:function(geometry,style,featureId){style=OpenLayers.Util.applyDefaults({fill:false},style);this.drawLinearRing(geometry,style,featureId);},drawLinearRing:function(geometry,style,featureId){if(style.fill!==false){this.setCanvasStyle("fill",style);this.renderPath(this.canvas,geometry,style,featureId,"fill");if(this.hitDetection){this.setHitContextStyle("fill",featureId,style);this.renderPath(this.hitContext,geometry,style,featureId,"fill");}}
+if(style.stroke!==false){this.setCanvasStyle("stroke",style);this.renderPath(this.canvas,geometry,style,featureId,"stroke");if(this.hitDetection){this.setHitContextStyle("stroke",featureId,style);this.renderPath(this.hitContext,geometry,style,featureId,"stroke");}}
+this.setCanvasStyle("reset");},renderPath:function(context,geometry,style,featureId,type){var components=geometry.components;var len=components.length;context.beginPath();var start=this.getLocalXY(components[0]);var x=start[0];var y=start[1];if(!isNaN(x)&&!isNaN(y)){context.moveTo(start[0],start[1]);for(var i=1;i<len;++i){var pt=this.getLocalXY(components[i]);context.lineTo(pt[0],pt[1]);}
+if(type==="fill"){context.fill();}else{context.stroke();}}},drawPolygon:function(geometry,style,featureId){var components=geometry.components;var len=components.length;this.drawLinearRing(components[0],style,featureId);for(var i=1;i<len;++i){this.canvas.globalCompositeOperation="destination-out";if(this.hitDetection){this.hitContext.globalCompositeOperation="destination-out";}
+this.drawLinearRing(components[i],OpenLayers.Util.applyDefaults({stroke:false,fillOpacity:1.0},style),featureId);this.canvas.globalCompositeOperation="source-over";if(this.hitDetection){this.hitContext.globalCompositeOperation="source-over";}
+this.drawLinearRing(components[i],OpenLayers.Util.applyDefaults({fill:false},style),featureId);}},drawText:function(location,style){var pt=this.getLocalXY(location);this.setCanvasStyle("reset");this.canvas.fillStyle=style.fontColor;this.canvas.globalAlpha=style.fontOpacity||1.0;var fontStyle=[style.fontStyle?style.fontStyle:"normal","normal",style.fontWeight?style.fontWeight:"normal",style.fontSize?style.fontSize:"1em",style.fontFamily?style.fontFamily:"sans-serif"].join(" ");var labelRows=style.label.split('\n');var numRows=labelRows.length;if(this.canvas.fillText){this.canvas.font=fontStyle;this.canvas.textAlign=OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[0]]||"center";this.canvas.textBaseline=OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[1]]||"middle";var vfactor=OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[1]];if(vfactor==null){vfactor=-.5;}
+var lineHeight=this.canvas.measureText('Mg').height||this.canvas.measureText('xx').width;pt[1]+=lineHeight*vfactor*(numRows-1);for(var i=0;i<numRows;i++){if(style.labelOutlineWidth){this.canvas.save();this.canvas.strokeStyle=style.labelOutlineColor;this.canvas.lineWidth=style.labelOutlineWidth;this.canvas.strokeText(labelRows[i],pt[0],pt[1]+(lineHeight*i)+1);this.canvas.restore();}
+this.canvas.fillText(labelRows[i],pt[0],pt[1]+(lineHeight*i));}}else if(this.canvas.mozDrawText){this.canvas.mozTextStyle=fontStyle;var hfactor=OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[0]];if(hfactor==null){hfactor=-.5;}
+var vfactor=OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[1]];if(vfactor==null){vfactor=-.5;}
+var lineHeight=this.canvas.mozMeasureText('xx');pt[1]+=lineHeight*(1+(vfactor*numRows));for(var i=0;i<numRows;i++){var x=pt[0]+(hfactor*this.canvas.mozMeasureText(labelRows[i]));var y=pt[1]+(i*lineHeight);this.canvas.translate(x,y);this.canvas.mozDrawText(labelRows[i]);this.canvas.translate(-x,-y);}}
+this.setCanvasStyle("reset");},getLocalXY:function(point){var resolution=this.getResolution();var extent=this.extent;var x=((point.x-this.featureDx)/resolution+(-extent.left/resolution));var y=((extent.top/resolution)-point.y/resolution);return[x,y];},clear:function(){var height=this.root.height;var width=this.root.width;this.canvas.clearRect(0,0,width,height);this.features={};if(this.hitDetection){this.hitContext.clearRect(0,0,width,height);}},getFeatureIdFromEvent:function(evt){var featureId,feature;if(this.hitDetection&&this.root.style.display!=="none"){if(!this.map.dragging){var xy=evt.xy;var x=xy.x|0;var y=xy.y|0;var data=this.hitContext.getImageData(x,y,1,1).data;if(data[3]===255){var id=data[2]+(256*(data[1]+(256*data[0])));if(id){featureId="OpenLayers.Feature.Vector_"+(id-1+this.hitOverflow);try{feature=this.features[featureId][0];}catch(err){}}}}}
+return feature;},eraseFeatures:function(features){if(!(OpenLayers.Util.isArray(features))){features=[features];}
+for(var i=0;i<features.length;++i){delete this.features[features[i].id];}
+this.redraw();},redraw:function(){if(!this.locked){var height=this.root.height;var width=this.root.width;this.canvas.clearRect(0,0,width,height);if(this.hitDetection){this.hitContext.clearRect(0,0,width,height);}
+var labelMap=[];var feature,geometry,style;var worldBounds=(this.map.baseLayer&&this.map.baseLayer.wrapDateLine)&&this.map.getMaxExtent();for(var id in this.features){if(!this.features.hasOwnProperty(id)){continue;}
+feature=this.features[id][0];geometry=feature.geometry;this.calculateFeatureDx(geometry.getBounds(),worldBounds);style=this.features[id][1];this.drawGeometry(geometry,style,feature.id);if(style.label){labelMap.push([feature,style]);}}
+var item;for(var i=0,len=labelMap.length;i<len;++i){item=labelMap[i];this.drawText(item[0].geometry.getCentroid(),item[1]);}}},CLASS_NAME:"OpenLayers.Renderer.Canvas"});OpenLayers.Renderer.Canvas.LABEL_ALIGN={"l":"left","r":"right","t":"top","b":"bottom"};OpenLayers.Renderer.Canvas.LABEL_FACTOR={"l":0,"r":-1,"t":0,"b":-1};OpenLayers.Renderer.Canvas.drawImageScaleFactor=null;OpenLayers.Format=OpenLayers.Class({options:null,externalProjection:null,internalProjection:null,data:null,keepData:false,initialize:function(options){OpenLayers.Util.extend(this,options);this.options=options;},destroy:function(){},read:function(data){throw new Error('Read not implemented.');},write:function(object){throw new Error('Write not implemented.');},CLASS_NAME:"OpenLayers.Format"});OpenLayers.Format.XML=OpenLayers.Class(OpenLayers.Format,{namespaces:null,namespaceAlias:null,defaultPrefix:null,readers:{},writers:{},xmldom:null,initialize:function(options){if(window.ActiveXObject){this.xmldom=new ActiveXObject("Microsoft.XMLDOM");}
+OpenLayers.Format.prototype.initialize.apply(this,[options]);this.namespaces=OpenLayers.Util.extend({},this.namespaces);this.namespaceAlias={};for(var alias in this.namespaces){this.namespaceAlias[this.namespaces[alias]]=alias;}},destroy:function(){this.xmldom=null;OpenLayers.Format.prototype.destroy.apply(this,arguments);},setNamespace:function(alias,uri){this.namespaces[alias]=uri;this.namespaceAlias[uri]=alias;},read:function(text){var index=text.indexOf('<');if(index>0){text=text.substring(index);}
+var node=OpenLayers.Util.Try(OpenLayers.Function.bind((function(){var xmldom;if(window.ActiveXObject&&!this.xmldom){xmldom=new ActiveXObject("Microsoft.XMLDOM");}else{xmldom=this.xmldom;}
+xmldom.loadXML(text);return xmldom;}),this),function(){return new DOMParser().parseFromString(text,'text/xml');},function(){var req=new XMLHttpRequest();req.open("GET","data:"+"text/xml"+";charset=utf-8,"+encodeURIComponent(text),false);if(req.overrideMimeType){req.overrideMimeType("text/xml");}
+req.send(null);return req.responseXML;});if(this.keepData){this.data=node;}
+return node;},write:function(node){var data;if(this.xmldom){data=node.xml;}else{var serializer=new XMLSerializer();if(node.nodeType==1){var doc=document.implementation.createDocument("","",null);if(doc.importNode){node=doc.importNode(node,true);}
+doc.appendChild(node);data=serializer.serializeToString(doc);}else{data=serializer.serializeToString(node);}}
+return data;},createElementNS:function(uri,name){var element;if(this.xmldom){if(typeof uri=="string"){element=this.xmldom.createNode(1,name,uri);}else{element=this.xmldom.createNode(1,name,"");}}else{element=document.createElementNS(uri,name);}
+return element;},createTextNode:function(text){var node;if(typeof text!=="string"){text=String(text);}
+if(this.xmldom){node=this.xmldom.createTextNode(text);}else{node=document.createTextNode(text);}
+return node;},getElementsByTagNameNS:function(node,uri,name){var elements=[];if(node.getElementsByTagNameNS){elements=node.getElementsByTagNameNS(uri,name);}else{var allNodes=node.getElementsByTagName("*");var potentialNode,fullName;for(var i=0,len=allNodes.length;i<len;++i){potentialNode=allNodes[i];fullName=(potentialNode.prefix)?(potentialNode.prefix+":"+name):name;if((name=="*")||(fullName==potentialNode.nodeName)){if((uri=="*")||(uri==potentialNode.namespaceURI)){elements.push(potentialNode);}}}}
+return elements;},getAttributeNodeNS:function(node,uri,name){var attributeNode=null;if(node.getAttributeNodeNS){attributeNode=node.getAttributeNodeNS(uri,name);}else{var attributes=node.attributes;var potentialNode,fullName;for(var i=0,len=attributes.length;i<len;++i){potentialNode=attributes[i];if(potentialNode.namespaceURI==uri){fullName=(potentialNode.prefix)?(potentialNode.prefix+":"+name):name;if(fullName==potentialNode.nodeName){attributeNode=potentialNode;break;}}}}
+return attributeNode;},getAttributeNS:function(node,uri,name){var attributeValue="";if(node.getAttributeNS){attributeValue=node.getAttributeNS(uri,name)||"";}else{var attributeNode=this.getAttributeNodeNS(node,uri,name);if(attributeNode){attributeValue=attributeNode.nodeValue;}}
+return attributeValue;},getChildValue:function(node,def){var value=def||"";if(node){for(var child=node.firstChild;child;child=child.nextSibling){switch(child.nodeType){case 3:case 4:value+=child.nodeValue;}}}
+return value;},isSimpleContent:function(node){var simple=true;for(var child=node.firstChild;child;child=child.nextSibling){if(child.nodeType===1){simple=false;break;}}
+return simple;},contentType:function(node){var simple=false,complex=false;var type=OpenLayers.Format.XML.CONTENT_TYPE.EMPTY;for(var child=node.firstChild;child;child=child.nextSibling){switch(child.nodeType){case 1:complex=true;break;case 8:break;default:simple=true;}
+if(complex&&simple){break;}}
+if(complex&&simple){type=OpenLayers.Format.XML.CONTENT_TYPE.MIXED;}else if(complex){return OpenLayers.Format.XML.CONTENT_TYPE.COMPLEX;}else if(simple){return OpenLayers.Format.XML.CONTENT_TYPE.SIMPLE;}
+return type;},hasAttributeNS:function(node,uri,name){var found=false;if(node.hasAttributeNS){found=node.hasAttributeNS(uri,name);}else{found=!!this.getAttributeNodeNS(node,uri,name);}
+return found;},setAttributeNS:function(node,uri,name,value){if(node.setAttributeNS){node.setAttributeNS(uri,name,value);}else{if(this.xmldom){if(uri){var attribute=node.ownerDocument.createNode(2,name,uri);attribute.nodeValue=value;node.setAttributeNode(attribute);}else{node.setAttribute(name,value);}}else{throw"setAttributeNS not implemented";}}},createElementNSPlus:function(name,options){options=options||{};var uri=options.uri||this.namespaces[options.prefix];if(!uri){var loc=name.indexOf(":");uri=this.namespaces[name.substring(0,loc)];}
+if(!uri){uri=this.namespaces[this.defaultPrefix];}
+var node=this.createElementNS(uri,name);if(options.attributes){this.setAttributes(node,options.attributes);}
+var value=options.value;if(value!=null){node.appendChild(this.createTextNode(value));}
+return node;},setAttributes:function(node,obj){var value,uri;for(var name in obj){if(obj[name]!=null&&obj[name].toString){value=obj[name].toString();uri=this.namespaces[name.substring(0,name.indexOf(":"))]||null;this.setAttributeNS(node,uri,name,value);}}},readNode:function(node,obj){if(!obj){obj={};}
+var group=this.readers[node.namespaceURI?this.namespaceAlias[node.namespaceURI]:this.defaultPrefix];if(group){var local=node.localName||node.nodeName.split(":").pop();var reader=group[local]||group["*"];if(reader){reader.apply(this,[node,obj]);}}
+return obj;},readChildNodes:function(node,obj){if(!obj){obj={};}
+var children=node.childNodes;var child;for(var i=0,len=children.length;i<len;++i){child=children[i];if(child.nodeType==1){this.readNode(child,obj);}}
+return obj;},writeNode:function(name,obj,parent){var prefix,local;var split=name.indexOf(":");if(split>0){prefix=name.substring(0,split);local=name.substring(split+1);}else{if(parent){prefix=this.namespaceAlias[parent.namespaceURI];}else{prefix=this.defaultPrefix;}
+local=name;}
+var child=this.writers[prefix][local].apply(this,[obj]);if(parent){parent.appendChild(child);}
+return child;},getChildEl:function(node,name,uri){return node&&this.getThisOrNextEl(node.firstChild,name,uri);},getNextEl:function(node,name,uri){return node&&this.getThisOrNextEl(node.nextSibling,name,uri);},getThisOrNextEl:function(node,name,uri){outer:for(var sibling=node;sibling;sibling=sibling.nextSibling){switch(sibling.nodeType){case 1:if((!name||name===(sibling.localName||sibling.nodeName.split(":").pop()))&&(!uri||uri===sibling.namespaceURI)){break outer;}
+sibling=null;break outer;case 3:if(/^\s*$/.test(sibling.nodeValue)){break;}
+case 4:case 6:case 12:case 10:case 11:sibling=null;break outer;}}
+return sibling||null;},lookupNamespaceURI:function(node,prefix){var uri=null;if(node){if(node.lookupNamespaceURI){uri=node.lookupNamespaceURI(prefix);}else{outer:switch(node.nodeType){case 1:if(node.namespaceURI!==null&&node.prefix===prefix){uri=node.namespaceURI;break outer;}
+var len=node.attributes.length;if(len){var attr;for(var i=0;i<len;++i){attr=node.attributes[i];if(attr.prefix==="xmlns"&&attr.name==="xmlns:"+prefix){uri=attr.value||null;break outer;}else if(attr.name==="xmlns"&&prefix===null){uri=attr.value||null;break outer;}}}
+uri=this.lookupNamespaceURI(node.parentNode,prefix);break outer;case 2:uri=this.lookupNamespaceURI(node.ownerElement,prefix);break outer;case 9:uri=this.lookupNamespaceURI(node.documentElement,prefix);break outer;case 6:case 12:case 10:case 11:break outer;default:uri=this.lookupNamespaceURI(node.parentNode,prefix);break outer;}}}
+return uri;},getXMLDoc:function(){if(!OpenLayers.Format.XML.document&&!this.xmldom){if(document.implementation&&document.implementation.createDocument){OpenLayers.Format.XML.document=document.implementation.createDocument("","",null);}else if(!this.xmldom&&window.ActiveXObject){this.xmldom=new ActiveXObject("Microsoft.XMLDOM");}}
+return OpenLayers.Format.XML.document||this.xmldom;},CLASS_NAME:"OpenLayers.Format.XML"});OpenLayers.Format.XML.CONTENT_TYPE={EMPTY:0,SIMPLE:1,COMPLEX:2,MIXED:3};OpenLayers.Format.XML.lookupNamespaceURI=OpenLayers.Function.bind(OpenLayers.Format.XML.prototype.lookupNamespaceURI,OpenLayers.Format.XML.prototype);OpenLayers.Format.XML.document=null;OpenLayers.Feature=OpenLayers.Class({layer:null,id:null,lonlat:null,data:null,marker:null,popupClass:null,popup:null,initialize:function(layer,lonlat,data){this.layer=layer;this.lonlat=lonlat;this.data=(data!=null)?data:{};this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){if((this.layer!=null)&&(this.layer.map!=null)){if(this.popup!=null){this.layer.map.removePopup(this.popup);}}
+if(this.layer!=null&&this.marker!=null){this.layer.removeMarker(this.marker);}
+this.layer=null;this.id=null;this.lonlat=null;this.data=null;if(this.marker!=null){this.destroyMarker(this.marker);this.marker=null;}
+if(this.popup!=null){this.destroyPopup(this.popup);this.popup=null;}},onScreen:function(){var onScreen=false;if((this.layer!=null)&&(this.layer.map!=null)){var screenBounds=this.layer.map.getExtent();onScreen=screenBounds.containsLonLat(this.lonlat);}
+return onScreen;},createMarker:function(){if(this.lonlat!=null){this.marker=new OpenLayers.Marker(this.lonlat,this.data.icon);}
+return this.marker;},destroyMarker:function(){this.marker.destroy();},createPopup:function(closeBox){if(this.lonlat!=null){if(!this.popup){var anchor=(this.marker)?this.marker.icon:null;var popupClass=this.popupClass?this.popupClass:OpenLayers.Popup.Anchored;this.popup=new popupClass(this.id+"_popup",this.lonlat,this.data.popupSize,this.data.popupContentHTML,anchor,closeBox);}
+if(this.data.overflow!=null){this.popup.contentDiv.style.overflow=this.data.overflow;}
+this.popup.feature=this;}
+return this.popup;},destroyPopup:function(){if(this.popup){this.popup.feature=null;this.popup.destroy();this.popup=null;}},CLASS_NAME:"OpenLayers.Feature"});OpenLayers.State={UNKNOWN:'Unknown',INSERT:'Insert',UPDATE:'Update',DELETE:'Delete'};OpenLayers.Feature.Vector=OpenLayers.Class(OpenLayers.Feature,{fid:null,geometry:null,attributes:null,bounds:null,state:null,style:null,url:null,renderIntent:"default",modified:null,initialize:function(geometry,attributes,style){OpenLayers.Feature.prototype.initialize.apply(this,[null,null,attributes]);this.lonlat=null;this.geometry=geometry?geometry:null;this.state=null;this.attributes={};if(attributes){this.attributes=OpenLayers.Util.extend(this.attributes,attributes);}
+this.style=style?style:null;},destroy:function(){if(this.layer){this.layer.removeFeatures(this);this.layer=null;}
+this.geometry=null;this.modified=null;OpenLayers.Feature.prototype.destroy.apply(this,arguments);},clone:function(){return new OpenLayers.Feature.Vector(this.geometry?this.geometry.clone():null,this.attributes,this.style);},onScreen:function(boundsOnly){var onScreen=false;if(this.layer&&this.layer.map){var screenBounds=this.layer.map.getExtent();if(boundsOnly){var featureBounds=this.geometry.getBounds();onScreen=screenBounds.intersectsBounds(featureBounds);}else{var screenPoly=screenBounds.toGeometry();onScreen=screenPoly.intersects(this.geometry);}}
+return onScreen;},getVisibility:function(){return!(this.style&&this.style.display=='none'||!this.layer||this.layer&&this.layer.styleMap&&this.layer.styleMap.createSymbolizer(this,this.renderIntent).display=='none'||this.layer&&!this.layer.getVisibility());},createMarker:function(){return null;},destroyMarker:function(){},createPopup:function(){return null;},atPoint:function(lonlat,toleranceLon,toleranceLat){var atPoint=false;if(this.geometry){atPoint=this.geometry.atPoint(lonlat,toleranceLon,toleranceLat);}
+return atPoint;},destroyPopup:function(){},move:function(location){if(!this.layer||!this.geometry.move){return undefined;}
+var pixel;if(location.CLASS_NAME=="OpenLayers.LonLat"){pixel=this.layer.getViewPortPxFromLonLat(location);}else{pixel=location;}
+var lastPixel=this.layer.getViewPortPxFromLonLat(this.geometry.getBounds().getCenterLonLat());var res=this.layer.map.getResolution();this.geometry.move(res*(pixel.x-lastPixel.x),res*(lastPixel.y-pixel.y));this.layer.drawFeature(this);return lastPixel;},toState:function(state){if(state==OpenLayers.State.UPDATE){switch(this.state){case OpenLayers.State.UNKNOWN:case OpenLayers.State.DELETE:this.state=state;break;case OpenLayers.State.UPDATE:case OpenLayers.State.INSERT:break;}}else if(state==OpenLayers.State.INSERT){switch(this.state){case OpenLayers.State.UNKNOWN:break;default:this.state=state;break;}}else if(state==OpenLayers.State.DELETE){switch(this.state){case OpenLayers.State.INSERT:break;case OpenLayers.State.DELETE:break;case OpenLayers.State.UNKNOWN:case OpenLayers.State.UPDATE:this.state=state;break;}}else if(state==OpenLayers.State.UNKNOWN){this.state=state;}},CLASS_NAME:"OpenLayers.Feature.Vector"});OpenLayers.Feature.Vector.style={'default':{fillColor:"#ee9900",fillOpacity:0.4,hoverFillColor:"white",hoverFillOpacity:0.8,strokeColor:"#ee9900",strokeOpacity:1,strokeWidth:1,strokeLinecap:"round",strokeDashstyle:"solid",hoverStrokeColor:"red",hoverStrokeOpacity:1,hoverStrokeWidth:0.2,pointRadius:6,hoverPointRadius:1,hoverPointUnit:"%",pointerEvents:"visiblePainted",cursor:"inherit",fontColor:"#000000",labelAlign:"cm",labelOutlineColor:"white",labelOutlineWidth:3},'select':{fillColor:"blue",fillOpacity:0.4,hoverFillColor:"white",hoverFillOpacity:0.8,strokeColor:"blue",strokeOpacity:1,strokeWidth:2,strokeLinecap:"round",strokeDashstyle:"solid",hoverStrokeColor:"red",hoverStrokeOpacity:1,hoverStrokeWidth:0.2,pointRadius:6,hoverPointRadius:1,hoverPointUnit:"%",pointerEvents:"visiblePainted",cursor:"pointer",fontColor:"#000000",labelAlign:"cm",labelOutlineColor:"white",labelOutlineWidth:3},'temporary':{fillColor:"#66cccc",fillOpacity:0.2,hoverFillColor:"white",hoverFillOpacity:0.8,strokeColor:"#66cccc",strokeOpacity:1,strokeLinecap:"round",strokeWidth:2,strokeDashstyle:"solid",hoverStrokeColor:"red",hoverStrokeOpacity:1,hoverStrokeWidth:0.2,pointRadius:6,hoverPointRadius:1,hoverPointUnit:"%",pointerEvents:"visiblePainted",cursor:"inherit",fontColor:"#000000",labelAlign:"cm",labelOutlineColor:"white",labelOutlineWidth:3},'delete':{display:"none"}};OpenLayers.Geometry.Polygon=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.LinearRing"],getArea:function(){var area=0.0;if(this.components&&(this.components.length>0)){area+=Math.abs(this.components[0].getArea());for(var i=1,len=this.components.length;i<len;i++){area-=Math.abs(this.components[i].getArea());}}
+return area;},getGeodesicArea:function(projection){var area=0.0;if(this.components&&(this.components.length>0)){area+=Math.abs(this.components[0].getGeodesicArea(projection));for(var i=1,len=this.components.length;i<len;i++){area-=Math.abs(this.components[i].getGeodesicArea(projection));}}
+return area;},containsPoint:function(point){var numRings=this.components.length;var contained=false;if(numRings>0){contained=this.components[0].containsPoint(point);if(contained!==1){if(contained&&numRings>1){var hole;for(var i=1;i<numRings;++i){hole=this.components[i].containsPoint(point);if(hole){if(hole===1){contained=1;}else{contained=false;}
+break;}}}}}
+return contained;},intersects:function(geometry){var intersect=false;var i,len;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){intersect=this.containsPoint(geometry);}else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LineString"||geometry.CLASS_NAME=="OpenLayers.Geometry.LinearRing"){for(i=0,len=this.components.length;i<len;++i){intersect=geometry.intersects(this.components[i]);if(intersect){break;}}
+if(!intersect){for(i=0,len=geometry.components.length;i<len;++i){intersect=this.containsPoint(geometry.components[i]);if(intersect){break;}}}}else{for(i=0,len=geometry.components.length;i<len;++i){intersect=this.intersects(geometry.components[i]);if(intersect){break;}}}
+if(!intersect&&geometry.CLASS_NAME=="OpenLayers.Geometry.Polygon"){var ring=this.components[0];for(i=0,len=ring.components.length;i<len;++i){intersect=geometry.containsPoint(ring.components[i]);if(intersect){break;}}}
+return intersect;},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var result;if(!edge&&this.intersects(geometry)){result=0;}else{result=OpenLayers.Geometry.Collection.prototype.distanceTo.apply(this,[geometry,options]);}
+return result;},CLASS_NAME:"OpenLayers.Geometry.Polygon"});OpenLayers.Geometry.Polygon.createRegularPolygon=function(origin,radius,sides,rotation){var angle=Math.PI*((1/sides)-(1/2));if(rotation){angle+=(rotation/180)*Math.PI;}
+var rotatedAngle,x,y;var points=[];for(var i=0;i<sides;++i){rotatedAngle=angle+(i*2*Math.PI/sides);x=origin.x+(radius*Math.cos(rotatedAngle));y=origin.y+(radius*Math.sin(rotatedAngle));points.push(new OpenLayers.Geometry.Point(x,y));}
+var ring=new OpenLayers.Geometry.LinearRing(points);return new OpenLayers.Geometry.Polygon([ring]);};OpenLayers.Format.OSM=OpenLayers.Class(OpenLayers.Format.XML,{checkTags:false,interestingTagsExclude:null,areaTags:null,initialize:function(options){var layer_defaults={'interestingTagsExclude':['source','source_ref','source:ref','history','attribution','created_by'],'areaTags':['area','building','leisure','tourism','ruins','historic','landuse','military','natural','sport']};layer_defaults=OpenLayers.Util.extend(layer_defaults,options);var interesting={};for(var i=0;i<layer_defaults.interestingTagsExclude.length;i++){interesting[layer_defaults.interestingTagsExclude[i]]=true;}
+layer_defaults.interestingTagsExclude=interesting;var area={};for(var i=0;i<layer_defaults.areaTags.length;i++){area[layer_defaults.areaTags[i]]=true;}
+layer_defaults.areaTags=area;this.externalProjection=new OpenLayers.Projection("EPSG:4326");OpenLayers.Format.XML.prototype.initialize.apply(this,[layer_defaults]);},read:function(doc){if(typeof doc=="string"){doc=OpenLayers.Format.XML.prototype.read.apply(this,[doc]);}
+var nodes=this.getNodes(doc);var ways=this.getWays(doc);var feat_list=new Array(ways.length);for(var i=0;i<ways.length;i++){var point_list=new Array(ways[i].nodes.length);var poly=this.isWayArea(ways[i])?1:0;for(var j=0;j<ways[i].nodes.length;j++){var node=nodes[ways[i].nodes[j]];var point=new OpenLayers.Geometry.Point(node.lon,node.lat);point.osm_id=parseInt(ways[i].nodes[j]);point_list[j]=point;node.used=true;}
+var geometry=null;if(poly){geometry=new OpenLayers.Geometry.Polygon(new OpenLayers.Geometry.LinearRing(point_list));}else{geometry=new OpenLayers.Geometry.LineString(point_list);}
+if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}
+var feat=new OpenLayers.Feature.Vector(geometry,ways[i].tags);feat.osm_id=parseInt(ways[i].id);feat.fid="way."+feat.osm_id;feat_list[i]=feat;}
+for(var node_id in nodes){var node=nodes[node_id];if(!node.used||this.checkTags){var tags=null;if(this.checkTags){var result=this.getTags(node.node,true);if(node.used&&!result[1]){continue;}
+tags=result[0];}else{tags=this.getTags(node.node);}
+var feat=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(node['lon'],node['lat']),tags);if(this.internalProjection&&this.externalProjection){feat.geometry.transform(this.externalProjection,this.internalProjection);}
+feat.osm_id=parseInt(node_id);feat.fid="node."+feat.osm_id;feat_list.push(feat);}
+node.node=null;}
+return feat_list;},getNodes:function(doc){var node_list=doc.getElementsByTagName("node");var nodes={};for(var i=0;i<node_list.length;i++){var node=node_list[i];var id=node.getAttribute("id");nodes[id]={'lat':node.getAttribute("lat"),'lon':node.getAttribute("lon"),'node':node};}
+return nodes;},getWays:function(doc){var way_list=doc.getElementsByTagName("way");var return_ways=[];for(var i=0;i<way_list.length;i++){var way=way_list[i];var way_object={id:way.getAttribute("id")};way_object.tags=this.getTags(way);var node_list=way.getElementsByTagName("nd");way_object.nodes=new Array(node_list.length);for(var j=0;j<node_list.length;j++){way_object.nodes[j]=node_list[j].getAttribute("ref");}
+return_ways.push(way_object);}
+return return_ways;},getTags:function(dom_node,interesting_tags){var tag_list=dom_node.getElementsByTagName("tag");var tags={};var interesting=false;for(var j=0;j<tag_list.length;j++){var key=tag_list[j].getAttribute("k");tags[key]=tag_list[j].getAttribute("v");if(interesting_tags){if(!this.interestingTagsExclude[key]){interesting=true;}}}
+return interesting_tags?[tags,interesting]:tags;},isWayArea:function(way){var poly_shaped=false;var poly_tags=false;if(way.nodes[0]==way.nodes[way.nodes.length-1]){poly_shaped=true;}
+if(this.checkTags){for(var key in way.tags){if(this.areaTags[key]){poly_tags=true;break;}}}
+return poly_shaped&&(this.checkTags?poly_tags:true);},write:function(features){if(!(OpenLayers.Util.isArray(features))){features=[features];}
+this.osm_id=1;this.created_nodes={};var root_node=this.createElementNS(null,"osm");root_node.setAttribute("version","0.5");root_node.setAttribute("generator","OpenLayers "+OpenLayers.VERSION_NUMBER);for(var i=features.length-1;i>=0;i--){var nodes=this.createFeatureNodes(features[i]);for(var j=0;j<nodes.length;j++){root_node.appendChild(nodes[j]);}}
+return OpenLayers.Format.XML.prototype.write.apply(this,[root_node]);},createFeatureNodes:function(feature){var nodes=[];var className=feature.geometry.CLASS_NAME;var type=className.substring(className.lastIndexOf(".")+1);type=type.toLowerCase();var builder=this.createXML[type];if(builder){nodes=builder.apply(this,[feature]);}
+return nodes;},createXML:{'point':function(point){var id=null;var geometry=point.geometry?point.geometry:point;if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);}
+var already_exists=false;if(point.osm_id){id=point.osm_id;if(this.created_nodes[id]){already_exists=true;}}else{id=-this.osm_id;this.osm_id++;}
+if(already_exists){node=this.created_nodes[id];}else{var node=this.createElementNS(null,"node");}
+this.created_nodes[id]=node;node.setAttribute("id",id);node.setAttribute("lon",geometry.x);node.setAttribute("lat",geometry.y);if(point.attributes){this.serializeTags(point,node);}
+this.setState(point,node);return already_exists?[]:[node];},linestring:function(feature){var id;var nodes=[];var geometry=feature.geometry;if(feature.osm_id){id=feature.osm_id;}else{id=-this.osm_id;this.osm_id++;}
+var way=this.createElementNS(null,"way");way.setAttribute("id",id);for(var i=0;i<geometry.components.length;i++){var node=this.createXML['point'].apply(this,[geometry.components[i]]);if(node.length){node=node[0];var node_ref=node.getAttribute("id");nodes.push(node);}else{node_ref=geometry.components[i].osm_id;node=this.created_nodes[node_ref];}
+this.setState(feature,node);var nd_dom=this.createElementNS(null,"nd");nd_dom.setAttribute("ref",node_ref);way.appendChild(nd_dom);}
+this.serializeTags(feature,way);nodes.push(way);return nodes;},polygon:function(feature){var attrs=OpenLayers.Util.extend({'area':'yes'},feature.attributes);var feat=new OpenLayers.Feature.Vector(feature.geometry.components[0],attrs);feat.osm_id=feature.osm_id;return this.createXML['linestring'].apply(this,[feat]);}},serializeTags:function(feature,node){for(var key in feature.attributes){var tag=this.createElementNS(null,"tag");tag.setAttribute("k",key);tag.setAttribute("v",feature.attributes[key]);node.appendChild(tag);}},setState:function(feature,node){if(feature.state){var state=null;switch(feature.state){case OpenLayers.State.UPDATE:state="modify";case OpenLayers.State.DELETE:state="delete";}
+if(state){node.setAttribute("action",state);}}},CLASS_NAME:"OpenLayers.Format.OSM"});OpenLayers.Handler=OpenLayers.Class({id:null,control:null,map:null,keyMask:null,active:false,evt:null,initialize:function(control,callbacks,options){OpenLayers.Util.extend(this,options);this.control=control;this.callbacks=callbacks;var map=this.map||control.map;if(map){this.setMap(map);}
+this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},setMap:function(map){this.map=map;},checkModifiers:function(evt){if(this.keyMask==null){return true;}
+var keyModifiers=(evt.shiftKey?OpenLayers.Handler.MOD_SHIFT:0)|(evt.ctrlKey?OpenLayers.Handler.MOD_CTRL:0)|(evt.altKey?OpenLayers.Handler.MOD_ALT:0);return(keyModifiers==this.keyMask);},activate:function(){if(this.active){return false;}
+var events=OpenLayers.Events.prototype.BROWSER_EVENTS;for(var i=0,len=events.length;i<len;i++){if(this[events[i]]){this.register(events[i],this[events[i]]);}}
+this.active=true;return true;},deactivate:function(){if(!this.active){return false;}
+var events=OpenLayers.Events.prototype.BROWSER_EVENTS;for(var i=0,len=events.length;i<len;i++){if(this[events[i]]){this.unregister(events[i],this[events[i]]);}}
+this.active=false;return true;},callback:function(name,args){if(name&&this.callbacks[name]){this.callbacks[name].apply(this.control,args);}},register:function(name,method){this.map.events.registerPriority(name,this,method);this.map.events.registerPriority(name,this,this.setEvent);},unregister:function(name,method){this.map.events.unregister(name,this,method);this.map.events.unregister(name,this,this.setEvent);},setEvent:function(evt){this.evt=evt;return true;},destroy:function(){this.deactivate();this.control=this.map=null;},CLASS_NAME:"OpenLayers.Handler"});OpenLayers.Handler.MOD_NONE=0;OpenLayers.Handler.MOD_SHIFT=1;OpenLayers.Handler.MOD_CTRL=2;OpenLayers.Handler.MOD_ALT=4;OpenLayers.Handler.MouseWheel=OpenLayers.Class(OpenLayers.Handler,{wheelListener:null,mousePosition:null,interval:0,delta:0,cumulative:true,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);this.wheelListener=OpenLayers.Function.bindAsEventListener(this.onWheelEvent,this);},destroy:function(){OpenLayers.Handler.prototype.destroy.apply(this,arguments);this.wheelListener=null;},onWheelEvent:function(e){if(!this.map||!this.checkModifiers(e)){return;}
+var overScrollableDiv=false;var overLayerDiv=false;var overMapDiv=false;var elem=OpenLayers.Event.element(e);while((elem!=null)&&!overMapDiv&&!overScrollableDiv){if(!overScrollableDiv){try{if(elem.currentStyle){overflow=elem.currentStyle["overflow"];}else{var style=document.defaultView.getComputedStyle(elem,null);var overflow=style.getPropertyValue("overflow");}
+overScrollableDiv=(overflow&&(overflow=="auto")||(overflow=="scroll"));}catch(err){}}
+if(!overLayerDiv){for(var i=0,len=this.map.layers.length;i<len;i++){if(elem==this.map.layers[i].div||elem==this.map.layers[i].pane){overLayerDiv=true;break;}}}
+overMapDiv=(elem==this.map.div);elem=elem.parentNode;}
+if(!overScrollableDiv&&overMapDiv){if(overLayerDiv){var delta=0;if(!e){e=window.event;}
+if(e.wheelDelta){delta=e.wheelDelta/120;if(window.opera&&window.opera.version()<9.2){delta=-delta;}}else if(e.detail){delta=-e.detail/3;}
+this.delta=this.delta+delta;if(this.interval){window.clearTimeout(this._timeoutId);this._timeoutId=window.setTimeout(OpenLayers.Function.bind(function(){this.wheelZoom(e);},this),this.interval);}else{this.wheelZoom(e);}}
+OpenLayers.Event.stop(e);}},wheelZoom:function(e){var delta=this.delta;this.delta=0;if(delta){if(this.mousePosition){e.xy=this.mousePosition;}
+if(!e.xy){e.xy=this.map.getPixelFromLonLat(this.map.getCenter());}
+if(delta<0){this.callback("down",[e,this.cumulative?delta:-1]);}else{this.callback("up",[e,this.cumulative?delta:1]);}}},mousemove:function(evt){this.mousePosition=evt.xy;},activate:function(evt){if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){var wheelListener=this.wheelListener;OpenLayers.Event.observe(window,"DOMMouseScroll",wheelListener);OpenLayers.Event.observe(window,"mousewheel",wheelListener);OpenLayers.Event.observe(document,"mousewheel",wheelListener);return true;}else{return false;}},deactivate:function(evt){if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){var wheelListener=this.wheelListener;OpenLayers.Event.stopObserving(window,"DOMMouseScroll",wheelListener);OpenLayers.Event.stopObserving(window,"mousewheel",wheelListener);OpenLayers.Event.stopObserving(document,"mousewheel",wheelListener);return true;}else{return false;}},CLASS_NAME:"OpenLayers.Handler.MouseWheel"});OpenLayers.Lang.en={'unhandledRequest':"Unhandled request return ${statusText}",'Permalink':"Permalink",'Overlays':"Overlays",'Base Layer':"Base Layer",'noFID':"Can't update a feature for which there is no FID.",'browserNotSupported':"Your browser does not support vector rendering. Currently supported renderers are:\n${renderers}",'minZoomLevelError':"The minZoomLevel property is only intended for use "+"with the FixedZoomLevels-descendent layers. That this "+"wfs layer checks for minZoomLevel is a relic of the"+"past. We cannot, however, remove it without possibly "+"breaking OL based applications that may depend on it."+" Therefore we are deprecating it -- the minZoomLevel "+"check below will be removed at 3.0. Please instead "+"use min/max resolution setting as described here: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaction: SUCCESS ${response}",'commitFailed':"WFS Transaction: FAILED ${response}",'googleWarning':"The Google Layer was unable to load correctly.<br><br>"+"To get rid of this message, select a new BaseLayer "+"in the layer switcher in the upper-right corner.<br><br>"+"Most likely, this is because the Google Maps library "+"script was either not included, or does not contain the "+"correct API key for your site.<br><br>"+"Developers: For help getting this working correctly, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>click here</a>",'getLayerWarning':"The ${layerType} Layer was unable to load correctly.<br><br>"+"To get rid of this message, select a new BaseLayer "+"in the layer switcher in the upper-right corner.<br><br>"+"Most likely, this is because the ${layerLib} library "+"script was not correctly included.<br><br>"+"Developers: For help getting this working correctly, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>click here</a>",'Scale = 1 : ${scaleDenom}':"Scale = 1 : ${scaleDenom}",'W':'W','E':'E','N':'N','S':'S','Graticule':'Graticule','reprojectDeprecated':"You are using the 'reproject' option "+"on the ${layerName} layer. This option is deprecated: "+"its use was designed to support displaying data over commercial "+"basemaps, but that functionality should now be achieved by using "+"Spherical Mercator support. More information is available from "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"This method has been deprecated and will be removed in 3.0. "+"Please use ${newMethod} instead.",'proxyNeeded':"You probably need to set OpenLayers.ProxyHost to access ${url}."+"See http://trac.osgeo.org/openlayers/wiki/FrequentlyAskedQuestions#ProxyHost",'end':''};OpenLayers.Lang['en-CA']=OpenLayers.Util.applyDefaults({},OpenLayers.Lang["en"]);OpenLayers.Geometry.MultiLineString=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.LineString"],split:function(geometry,options){var results=null;var mutual=options&&options.mutual;var splits,sourceLine,sourceLines,sourceSplit,targetSplit;var sourceParts=[];var targetParts=[geometry];for(var i=0,len=this.components.length;i<len;++i){sourceLine=this.components[i];sourceSplit=false;for(var j=0;j<targetParts.length;++j){splits=sourceLine.split(targetParts[j],options);if(splits){if(mutual){sourceLines=splits[0];for(var k=0,klen=sourceLines.length;k<klen;++k){if(k===0&&sourceParts.length){sourceParts[sourceParts.length-1].addComponent(sourceLines[k]);}else{sourceParts.push(new OpenLayers.Geometry.MultiLineString([sourceLines[k]]));}}
+sourceSplit=true;splits=splits[1];}
+if(splits.length){splits.unshift(j,1);Array.prototype.splice.apply(targetParts,splits);break;}}}
+if(!sourceSplit){if(sourceParts.length){sourceParts[sourceParts.length-1].addComponent(sourceLine.clone());}else{sourceParts=[new OpenLayers.Geometry.MultiLineString(sourceLine.clone())];}}}
+if(sourceParts&&sourceParts.length>1){sourceSplit=true;}else{sourceParts=[];}
+if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];}
+if(sourceSplit||targetSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}}
+return results;},splitWith:function(geometry,options){var results=null;var mutual=options&&options.mutual;var splits,targetLine,sourceLines,sourceSplit,targetSplit,sourceParts,targetParts;if(geometry instanceof OpenLayers.Geometry.LineString){targetParts=[];sourceParts=[geometry];for(var i=0,len=this.components.length;i<len;++i){targetSplit=false;targetLine=this.components[i];for(var j=0;j<sourceParts.length;++j){splits=sourceParts[j].split(targetLine,options);if(splits){if(mutual){sourceLines=splits[0];if(sourceLines.length){sourceLines.unshift(j,1);Array.prototype.splice.apply(sourceParts,sourceLines);j+=sourceLines.length-2;}
+splits=splits[1];if(splits.length===0){splits=[targetLine.clone()];}}
+for(var k=0,klen=splits.length;k<klen;++k){if(k===0&&targetParts.length){targetParts[targetParts.length-1].addComponent(splits[k]);}else{targetParts.push(new OpenLayers.Geometry.MultiLineString([splits[k]]));}}
+targetSplit=true;}}
+if(!targetSplit){if(targetParts.length){targetParts[targetParts.length-1].addComponent(targetLine.clone());}else{targetParts=[new OpenLayers.Geometry.MultiLineString([targetLine.clone()])];}}}}else{results=geometry.split(this);}
+if(sourceParts&&sourceParts.length>1){sourceSplit=true;}else{sourceParts=[];}
+if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];}
+if(sourceSplit||targetSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}}
+return results;},CLASS_NAME:"OpenLayers.Geometry.MultiLineString"});OpenLayers.Popup=OpenLayers.Class({events:null,id:"",lonlat:null,div:null,contentSize:null,size:null,contentHTML:null,backgroundColor:"",opacity:"",border:"",contentDiv:null,groupDiv:null,closeDiv:null,autoSize:false,minSize:null,maxSize:null,displayClass:"olPopup",contentDisplayClass:"olPopupContent",padding:0,disableFirefoxOverflowHack:false,fixPadding:function(){if(typeof this.padding=="number"){this.padding=new OpenLayers.Bounds(this.padding,this.padding,this.padding,this.padding);}},panMapIfOutOfView:false,keepInMap:false,closeOnMove:false,map:null,initialize:function(id,lonlat,contentSize,contentHTML,closeBox,closeBoxCallback){if(id==null){id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");}
+this.id=id;this.lonlat=lonlat;this.contentSize=(contentSize!=null)?contentSize:new OpenLayers.Size(OpenLayers.Popup.WIDTH,OpenLayers.Popup.HEIGHT);if(contentHTML!=null){this.contentHTML=contentHTML;}
+this.backgroundColor=OpenLayers.Popup.COLOR;this.opacity=OpenLayers.Popup.OPACITY;this.border=OpenLayers.Popup.BORDER;this.div=OpenLayers.Util.createDiv(this.id,null,null,null,null,null,"hidden");this.div.className=this.displayClass;var groupDivId=this.id+"_GroupDiv";this.groupDiv=OpenLayers.Util.createDiv(groupDivId,null,null,null,"relative",null,"hidden");var id=this.div.id+"_contentDiv";this.contentDiv=OpenLayers.Util.createDiv(id,null,this.contentSize.clone(),null,"relative");this.contentDiv.className=this.contentDisplayClass;this.groupDiv.appendChild(this.contentDiv);this.div.appendChild(this.groupDiv);if(closeBox){this.addCloseBox(closeBoxCallback);}
+this.registerEvents();},destroy:function(){this.id=null;this.lonlat=null;this.size=null;this.contentHTML=null;this.backgroundColor=null;this.opacity=null;this.border=null;if(this.closeOnMove&&this.map){this.map.events.unregister("movestart",this,this.hide);}
+this.events.destroy();this.events=null;if(this.closeDiv){OpenLayers.Event.stopObservingElement(this.closeDiv);this.groupDiv.removeChild(this.closeDiv);}
+this.closeDiv=null;this.div.removeChild(this.groupDiv);this.groupDiv=null;if(this.map!=null){this.map.removePopup(this);}
+this.map=null;this.div=null;this.autoSize=null;this.minSize=null;this.maxSize=null;this.padding=null;this.panMapIfOutOfView=null;},draw:function(px){if(px==null){if((this.lonlat!=null)&&(this.map!=null)){px=this.map.getLayerPxFromLonLat(this.lonlat);}}
+if(this.closeOnMove){this.map.events.register("movestart",this,this.hide);}
+if(!this.disableFirefoxOverflowHack&&OpenLayers.BROWSER_NAME=='firefox'){this.map.events.register("movestart",this,function(){var style=document.defaultView.getComputedStyle(this.contentDiv,null);var currentOverflow=style.getPropertyValue("overflow");if(currentOverflow!="hidden"){this.contentDiv._oldOverflow=currentOverflow;this.contentDiv.style.overflow="hidden";}});this.map.events.register("moveend",this,function(){var oldOverflow=this.contentDiv._oldOverflow;if(oldOverflow){this.contentDiv.style.overflow=oldOverflow;this.contentDiv._oldOverflow=null;}});}
+this.moveTo(px);if(!this.autoSize&&!this.size){this.setSize(this.contentSize);}
+this.setBackgroundColor();this.setOpacity();this.setBorder();this.setContentHTML();if(this.panMapIfOutOfView){this.panIntoView();}
+return this.div;},updatePosition:function(){if((this.lonlat)&&(this.map)){var px=this.map.getLayerPxFromLonLat(this.lonlat);if(px){this.moveTo(px);}}},moveTo:function(px){if((px!=null)&&(this.div!=null)){this.div.style.left=px.x+"px";this.div.style.top=px.y+"px";}},visible:function(){return OpenLayers.Element.visible(this.div);},toggle:function(){if(this.visible()){this.hide();}else{this.show();}},show:function(){this.div.style.display='';if(this.panMapIfOutOfView){this.panIntoView();}},hide:function(){this.div.style.display='none';},setSize:function(contentSize){this.size=contentSize.clone();var contentDivPadding=this.getContentDivPadding();var wPadding=contentDivPadding.left+contentDivPadding.right;var hPadding=contentDivPadding.top+contentDivPadding.bottom;this.fixPadding();wPadding+=this.padding.left+this.padding.right;hPadding+=this.padding.top+this.padding.bottom;if(this.closeDiv){var closeDivWidth=parseInt(this.closeDiv.style.width);wPadding+=closeDivWidth+contentDivPadding.right;}
+this.size.w+=wPadding;this.size.h+=hPadding;if(OpenLayers.BROWSER_NAME=="msie"){this.contentSize.w+=contentDivPadding.left+contentDivPadding.right;this.contentSize.h+=contentDivPadding.bottom+contentDivPadding.top;}
+if(this.div!=null){this.div.style.width=this.size.w+"px";this.div.style.height=this.size.h+"px";}
+if(this.contentDiv!=null){this.contentDiv.style.width=contentSize.w+"px";this.contentDiv.style.height=contentSize.h+"px";}},updateSize:function(){var preparedHTML="<div class='"+this.contentDisplayClass+"'>"+
+this.contentDiv.innerHTML+"</div>";var containerElement=(this.map)?this.map.div:document.body;var realSize=OpenLayers.Util.getRenderedDimensions(preparedHTML,null,{displayClass:this.displayClass,containerElement:containerElement});var safeSize=this.getSafeContentSize(realSize);var newSize=null;if(safeSize.equals(realSize)){newSize=realSize;}else{var fixedSize={w:(safeSize.w<realSize.w)?safeSize.w:null,h:(safeSize.h<realSize.h)?safeSize.h:null};if(fixedSize.w&&fixedSize.h){newSize=safeSize;}else{var clippedSize=OpenLayers.Util.getRenderedDimensions(preparedHTML,fixedSize,{displayClass:this.contentDisplayClass,containerElement:containerElement});var currentOverflow=OpenLayers.Element.getStyle(this.contentDiv,"overflow");if((currentOverflow!="hidden")&&(clippedSize.equals(safeSize))){var scrollBar=OpenLayers.Util.getScrollbarWidth();if(fixedSize.w){clippedSize.h+=scrollBar;}else{clippedSize.w+=scrollBar;}}
+newSize=this.getSafeContentSize(clippedSize);}}
+this.setSize(newSize);},setBackgroundColor:function(color){if(color!=undefined){this.backgroundColor=color;}
+if(this.div!=null){this.div.style.backgroundColor=this.backgroundColor;}},setOpacity:function(opacity){if(opacity!=undefined){this.opacity=opacity;}
+if(this.div!=null){this.div.style.opacity=this.opacity;this.div.style.filter='alpha(opacity='+this.opacity*100+')';}},setBorder:function(border){if(border!=undefined){this.border=border;}
+if(this.div!=null){this.div.style.border=this.border;}},setContentHTML:function(contentHTML){if(contentHTML!=null){this.contentHTML=contentHTML;}
+if((this.contentDiv!=null)&&(this.contentHTML!=null)&&(this.contentHTML!=this.contentDiv.innerHTML)){this.contentDiv.innerHTML=this.contentHTML;if(this.autoSize){this.registerImageListeners();this.updateSize();}}},registerImageListeners:function(){var onImgLoad=function(){if(this.popup.id===null){return;}
+this.popup.updateSize();if(this.popup.visible()&&this.popup.panMapIfOutOfView){this.popup.panIntoView();}
+OpenLayers.Event.stopObserving(this.img,"load",this.img._onImageLoad);};var images=this.contentDiv.getElementsByTagName("img");for(var i=0,len=images.length;i<len;i++){var img=images[i];if(img.width==0||img.height==0){var context={'popup':this,'img':img};img._onImgLoad=OpenLayers.Function.bind(onImgLoad,context);OpenLayers.Event.observe(img,'load',img._onImgLoad);}}},getSafeContentSize:function(size){var safeContentSize=size.clone();var contentDivPadding=this.getContentDivPadding();var wPadding=contentDivPadding.left+contentDivPadding.right;var hPadding=contentDivPadding.top+contentDivPadding.bottom;this.fixPadding();wPadding+=this.padding.left+this.padding.right;hPadding+=this.padding.top+this.padding.bottom;if(this.closeDiv){var closeDivWidth=parseInt(this.closeDiv.style.width);wPadding+=closeDivWidth+contentDivPadding.right;}
+if(this.minSize){safeContentSize.w=Math.max(safeContentSize.w,(this.minSize.w-wPadding));safeContentSize.h=Math.max(safeContentSize.h,(this.minSize.h-hPadding));}
+if(this.maxSize){safeContentSize.w=Math.min(safeContentSize.w,(this.maxSize.w-wPadding));safeContentSize.h=Math.min(safeContentSize.h,(this.maxSize.h-hPadding));}
+if(this.map&&this.map.size){var extraX=0,extraY=0;if(this.keepInMap&&!this.panMapIfOutOfView){var px=this.map.getPixelFromLonLat(this.lonlat);switch(this.relativePosition){case"tr":extraX=px.x;extraY=this.map.size.h-px.y;break;case"tl":extraX=this.map.size.w-px.x;extraY=this.map.size.h-px.y;break;case"bl":extraX=this.map.size.w-px.x;extraY=px.y;break;case"br":extraX=px.x;extraY=px.y;break;default:extraX=px.x;extraY=this.map.size.h-px.y;break;}}
+var maxY=this.map.size.h-
+this.map.paddingForPopups.top-
+this.map.paddingForPopups.bottom-
+hPadding-extraY;var maxX=this.map.size.w-
+this.map.paddingForPopups.left-
+this.map.paddingForPopups.right-
+wPadding-extraX;safeContentSize.w=Math.min(safeContentSize.w,maxX);safeContentSize.h=Math.min(safeContentSize.h,maxY);}
+return safeContentSize;},getContentDivPadding:function(){var contentDivPadding=this._contentDivPadding;if(!contentDivPadding){if(this.div.parentNode==null){this.div.style.display="none";document.body.appendChild(this.div);}
+contentDivPadding=new OpenLayers.Bounds(OpenLayers.Element.getStyle(this.contentDiv,"padding-left"),OpenLayers.Element.getStyle(this.contentDiv,"padding-bottom"),OpenLayers.Element.getStyle(this.contentDiv,"padding-right"),OpenLayers.Element.getStyle(this.contentDiv,"padding-top"));this._contentDivPadding=contentDivPadding;if(this.div.parentNode==document.body){document.body.removeChild(this.div);this.div.style.display="";}}
+return contentDivPadding;},addCloseBox:function(callback){this.closeDiv=OpenLayers.Util.createDiv(this.id+"_close",null,{w:17,h:17});this.closeDiv.className="olPopupCloseBox";var contentDivPadding=this.getContentDivPadding();this.closeDiv.style.right=contentDivPadding.right+"px";this.closeDiv.style.top=contentDivPadding.top+"px";this.groupDiv.appendChild(this.closeDiv);var closePopup=callback||function(e){this.hide();OpenLayers.Event.stop(e);};OpenLayers.Event.observe(this.closeDiv,"touchend",OpenLayers.Function.bindAsEventListener(closePopup,this));OpenLayers.Event.observe(this.closeDiv,"click",OpenLayers.Function.bindAsEventListener(closePopup,this));},panIntoView:function(){var mapSize=this.map.getSize();var origTL=this.map.getViewPortPxFromLayerPx(new OpenLayers.Pixel(parseInt(this.div.style.left),parseInt(this.div.style.top)));var newTL=origTL.clone();if(origTL.x<this.map.paddingForPopups.left){newTL.x=this.map.paddingForPopups.left;}else
+if((origTL.x+this.size.w)>(mapSize.w-this.map.paddingForPopups.right)){newTL.x=mapSize.w-this.map.paddingForPopups.right-this.size.w;}
+if(origTL.y<this.map.paddingForPopups.top){newTL.y=this.map.paddingForPopups.top;}else
+if((origTL.y+this.size.h)>(mapSize.h-this.map.paddingForPopups.bottom)){newTL.y=mapSize.h-this.map.paddingForPopups.bottom-this.size.h;}
+var dx=origTL.x-newTL.x;var dy=origTL.y-newTL.y;this.map.pan(dx,dy);},registerEvents:function(){this.events=new OpenLayers.Events(this,this.div,null,true);function onTouchstart(evt){OpenLayers.Event.stop(evt,true);}
+this.events.on({"mousedown":this.onmousedown,"mousemove":this.onmousemove,"mouseup":this.onmouseup,"click":this.onclick,"mouseout":this.onmouseout,"dblclick":this.ondblclick,"touchstart":onTouchstart,scope:this});},onmousedown:function(evt){this.mousedown=true;OpenLayers.Event.stop(evt,true);},onmousemove:function(evt){if(this.mousedown){OpenLayers.Event.stop(evt,true);}},onmouseup:function(evt){if(this.mousedown){this.mousedown=false;OpenLayers.Event.stop(evt,true);}},onclick:function(evt){OpenLayers.Event.stop(evt,true);},onmouseout:function(evt){this.mousedown=false;},ondblclick:function(evt){OpenLayers.Event.stop(evt,true);},CLASS_NAME:"OpenLayers.Popup"});OpenLayers.Popup.WIDTH=200;OpenLayers.Popup.HEIGHT=200;OpenLayers.Popup.COLOR="white";OpenLayers.Popup.OPACITY=1;OpenLayers.Popup.BORDER="0px";OpenLayers.Popup.Anchored=OpenLayers.Class(OpenLayers.Popup,{relativePosition:null,keepInMap:true,anchor:null,initialize:function(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){var newArguments=[id,lonlat,contentSize,contentHTML,closeBox,closeBoxCallback];OpenLayers.Popup.prototype.initialize.apply(this,newArguments);this.anchor=(anchor!=null)?anchor:{size:new OpenLayers.Size(0,0),offset:new OpenLayers.Pixel(0,0)};},destroy:function(){this.anchor=null;this.relativePosition=null;OpenLayers.Popup.prototype.destroy.apply(this,arguments);},show:function(){this.updatePosition();OpenLayers.Popup.prototype.show.apply(this,arguments);},moveTo:function(px){var oldRelativePosition=this.relativePosition;this.relativePosition=this.calculateRelativePosition(px);var newPx=this.calculateNewPx(px);var newArguments=new Array(newPx);OpenLayers.Popup.prototype.moveTo.apply(this,newArguments);if(this.relativePosition!=oldRelativePosition){this.updateRelativePosition();}},setSize:function(contentSize){OpenLayers.Popup.prototype.setSize.apply(this,arguments);if((this.lonlat)&&(this.map)){var px=this.map.getLayerPxFromLonLat(this.lonlat);this.moveTo(px);}},calculateRelativePosition:function(px){var lonlat=this.map.getLonLatFromLayerPx(px);var extent=this.map.getExtent();var quadrant=extent.determineQuadrant(lonlat);return OpenLayers.Bounds.oppositeQuadrant(quadrant);},updateRelativePosition:function(){},calculateNewPx:function(px){var newPx=px.offset(this.anchor.offset);var size=this.size||this.contentSize;var top=(this.relativePosition.charAt(0)=='t');newPx.y+=(top)?-size.h:this.anchor.size.h;var left=(this.relativePosition.charAt(1)=='l');newPx.x+=(left)?-size.w:this.anchor.size.w;return newPx;},CLASS_NAME:"OpenLayers.Popup.Anchored"});OpenLayers.Popup.Framed=OpenLayers.Class(OpenLayers.Popup.Anchored,{imageSrc:null,imageSize:null,isAlphaImage:false,positionBlocks:null,blocks:null,fixedRelativePosition:false,initialize:function(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){OpenLayers.Popup.Anchored.prototype.initialize.apply(this,arguments);if(this.fixedRelativePosition){this.updateRelativePosition();this.calculateRelativePosition=function(px){return this.relativePosition;};}
+this.contentDiv.style.position="absolute";this.contentDiv.style.zIndex=1;if(closeBox){this.closeDiv.style.zIndex=1;}
+this.groupDiv.style.position="absolute";this.groupDiv.style.top="0px";this.groupDiv.style.left="0px";this.groupDiv.style.height="100%";this.groupDiv.style.width="100%";},destroy:function(){this.imageSrc=null;this.imageSize=null;this.isAlphaImage=null;this.fixedRelativePosition=false;this.positionBlocks=null;for(var i=0;i<this.blocks.length;i++){var block=this.blocks[i];if(block.image){block.div.removeChild(block.image);}
+block.image=null;if(block.div){this.groupDiv.removeChild(block.div);}
+block.div=null;}
+this.blocks=null;OpenLayers.Popup.Anchored.prototype.destroy.apply(this,arguments);},setBackgroundColor:function(color){},setBorder:function(){},setOpacity:function(opacity){},setSize:function(contentSize){OpenLayers.Popup.Anchored.prototype.setSize.apply(this,arguments);this.updateBlocks();},updateRelativePosition:function(){this.padding=this.positionBlocks[this.relativePosition].padding;if(this.closeDiv){var contentDivPadding=this.getContentDivPadding();this.closeDiv.style.right=contentDivPadding.right+
+this.padding.right+"px";this.closeDiv.style.top=contentDivPadding.top+
+this.padding.top+"px";}
+this.updateBlocks();},calculateNewPx:function(px){var newPx=OpenLayers.Popup.Anchored.prototype.calculateNewPx.apply(this,arguments);newPx=newPx.offset(this.positionBlocks[this.relativePosition].offset);return newPx;},createBlocks:function(){this.blocks=[];var firstPosition=null;for(var key in this.positionBlocks){firstPosition=key;break;}
+var position=this.positionBlocks[firstPosition];for(var i=0;i<position.blocks.length;i++){var block={};this.blocks.push(block);var divId=this.id+'_FrameDecorationDiv_'+i;block.div=OpenLayers.Util.createDiv(divId,null,null,null,"absolute",null,"hidden",null);var imgId=this.id+'_FrameDecorationImg_'+i;var imageCreator=(this.isAlphaImage)?OpenLayers.Util.createAlphaImageDiv:OpenLayers.Util.createImage;block.image=imageCreator(imgId,null,this.imageSize,this.imageSrc,"absolute",null,null,null);block.div.appendChild(block.image);this.groupDiv.appendChild(block.div);}},updateBlocks:function(){if(!this.blocks){this.createBlocks();}
+if(this.size&&this.relativePosition){var position=this.positionBlocks[this.relativePosition];for(var i=0;i<position.blocks.length;i++){var positionBlock=position.blocks[i];var block=this.blocks[i];var l=positionBlock.anchor.left;var b=positionBlock.anchor.bottom;var r=positionBlock.anchor.right;var t=positionBlock.anchor.top;var w=(isNaN(positionBlock.size.w))?this.size.w-(r+l):positionBlock.size.w;var h=(isNaN(positionBlock.size.h))?this.size.h-(b+t):positionBlock.size.h;block.div.style.width=(w<0?0:w)+'px';block.div.style.height=(h<0?0:h)+'px';block.div.style.left=(l!=null)?l+'px':'';block.div.style.bottom=(b!=null)?b+'px':'';block.div.style.right=(r!=null)?r+'px':'';block.div.style.top=(t!=null)?t+'px':'';block.image.style.left=positionBlock.position.x+'px';block.image.style.top=positionBlock.position.y+'px';}
+this.contentDiv.style.left=this.padding.left+"px";this.contentDiv.style.top=this.padding.top+"px";}},CLASS_NAME:"OpenLayers.Popup.Framed"});OpenLayers.Popup.FramedCloud=OpenLayers.Class(OpenLayers.Popup.Framed,{contentDisplayClass:"olFramedCloudPopupContent",autoSize:true,panMapIfOutOfView:true,imageSize:new OpenLayers.Size(1276,736),isAlphaImage:false,fixedRelativePosition:false,positionBlocks:{"tl":{'offset':new OpenLayers.Pixel(44,0),'padding':new OpenLayers.Bounds(8,40,8,9),'blocks':[{size:new OpenLayers.Size('auto','auto'),anchor:new OpenLayers.Bounds(0,51,22,0),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,'auto'),anchor:new OpenLayers.Bounds(null,50,0,0),position:new OpenLayers.Pixel(-1238,0)},{size:new OpenLayers.Size('auto',19),anchor:new OpenLayers.Bounds(0,32,22,null),position:new OpenLayers.Pixel(0,-631)},{size:new OpenLayers.Size(22,18),anchor:new OpenLayers.Bounds(null,32,0,null),position:new OpenLayers.Pixel(-1238,-632)},{size:new OpenLayers.Size(81,35),anchor:new OpenLayers.Bounds(null,0,0,null),position:new OpenLayers.Pixel(0,-688)}]},"tr":{'offset':new OpenLayers.Pixel(-45,0),'padding':new OpenLayers.Bounds(8,40,8,9),'blocks':[{size:new OpenLayers.Size('auto','auto'),anchor:new OpenLayers.Bounds(0,51,22,0),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,'auto'),anchor:new OpenLayers.Bounds(null,50,0,0),position:new OpenLayers.Pixel(-1238,0)},{size:new OpenLayers.Size('auto',19),anchor:new OpenLayers.Bounds(0,32,22,null),position:new OpenLayers.Pixel(0,-631)},{size:new OpenLayers.Size(22,19),anchor:new OpenLayers.Bounds(null,32,0,null),position:new OpenLayers.Pixel(-1238,-631)},{size:new OpenLayers.Size(81,35),anchor:new OpenLayers.Bounds(0,0,null,null),position:new OpenLayers.Pixel(-215,-687)}]},"bl":{'offset':new OpenLayers.Pixel(45,0),'padding':new OpenLayers.Bounds(8,9,8,40),'blocks':[{size:new OpenLayers.Size('auto','auto'),anchor:new OpenLayers.Bounds(0,21,22,32),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,'auto'),anchor:new OpenLayers.Bounds(null,21,0,32),position:new OpenLayers.Pixel(-1238,0)},{size:new OpenLayers.Size('auto',21),anchor:new OpenLayers.Bounds(0,0,22,null),position:new OpenLayers.Pixel(0,-629)},{size:new OpenLayers.Size(22,21),anchor:new OpenLayers.Bounds(null,0,0,null),position:new OpenLayers.Pixel(-1238,-629)},{size:new OpenLayers.Size(81,33),anchor:new OpenLayers.Bounds(null,null,0,0),position:new OpenLayers.Pixel(-101,-674)}]},"br":{'offset':new OpenLayers.Pixel(-44,0),'padding':new OpenLayers.Bounds(8,9,8,40),'blocks':[{size:new OpenLayers.Size('auto','auto'),anchor:new OpenLayers.Bounds(0,21,22,32),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,'auto'),anchor:new OpenLayers.Bounds(null,21,0,32),position:new OpenLayers.Pixel(-1238,0)},{size:new OpenLayers.Size('auto',21),anchor:new OpenLayers.Bounds(0,0,22,null),position:new OpenLayers.Pixel(0,-629)},{size:new OpenLayers.Size(22,21),anchor:new OpenLayers.Bounds(null,0,0,null),position:new OpenLayers.Pixel(-1238,-629)},{size:new OpenLayers.Size(81,33),anchor:new OpenLayers.Bounds(0,null,null,0),position:new OpenLayers.Pixel(-311,-674)}]}},minSize:new OpenLayers.Size(105,10),maxSize:new OpenLayers.Size(1200,660),initialize:function(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){this.imageSrc=OpenLayers.Util.getImageLocation('cloud-popup-relative.png');OpenLayers.Popup.Framed.prototype.initialize.apply(this,arguments);this.contentDiv.className=this.contentDisplayClass;},CLASS_NAME:"OpenLayers.Popup.FramedCloud"});OpenLayers.Lang["nb"]={'unhandledRequest':"Ubehandlet forespørsel returnerte ${statusText}",'Permalink':"Kobling til denne siden",'Overlays':"Kartlag",'Base Layer':"Bakgrunnskart",'noFID':"Kan ikke oppdatere et feature (et objekt) som ikke har FID.",'browserNotSupported':"Din nettleser støtter ikke vektortegning. Tegnemetodene som støttes er:\n${renderers}",'minZoomLevelError':"Egenskapen minZoomLevel er kun ment til bruk på lag "+"basert på FixedZoomLevels. At dette wfs-laget sjekker "+"minZoomLevel er en etterlevning fra tidligere versjoner. Det kan dog ikke "+"tas bort uten å risikere at OL-baserte applikasjoner "+"slutter å virke, så det er merket som foreldet: "+"minZoomLevel i sjekken nedenfor vil fjernes i 3.0. "+"Vennligst bruk innstillingene for min/maks oppløsning "+"som er beskrevet her: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-transaksjon: LYKTES ${response}",'commitFailed':"WFS-transaksjon: MISLYKTES ${response}",'googleWarning':"Google-laget kunne ikke lastes.<br><br>"+"Bytt til et annet bakgrunnslag i lagvelgeren i "+"øvre høyre hjørne for å slippe denne meldingen.<br><br>"+"Sannsynligvis forårsakes feilen av at Google Maps-biblioteket "+"ikke er riktig inkludert på nettsiden, eller at det ikke er "+"angitt riktig API-nøkkel for nettstedet.<br><br>"+"Utviklere: For hjelp til å få dette til å virke se "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>her</a>.",'getLayerWarning':"${layerType}-laget kunne ikke lastes.<br><br>"+"Bytt til et annet bakgrunnslag i lagvelgeren i "+"øvre høyre hjørne for å slippe denne meldingen.<br><br>"+"Sannsynligvis forårsakes feilen av at "+"${layerLib}-biblioteket ikke var riktig inkludert "+"på nettsiden.<br><br>"+"Utviklere: For hjelp til å få dette til å virke se "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>her</a>.",'Scale = 1 : ${scaleDenom}':"<strong>Skala</strong> 1 : ${scaleDenom}",'reprojectDeprecated':"Du bruker innstillingen 'reproject' på laget ${layerName}. "+"Denne innstillingen er foreldet, den var ment for å støtte "+"visning av kartdata over kommersielle bakgrunnskart, men det "+"bør nå gjøres med støtten for Spherical Mercator. Mer informasjon "+"finnes på http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Denne metoden er markert som foreldet og vil bli fjernet i 3.0. "+"Vennligst bruk ${newMethod} i stedet.",'end':''};OpenLayers.Lang["no"]=OpenLayers.Lang["nb"];OpenLayers.ElementsIndexer=OpenLayers.Class({maxZIndex:null,order:null,indices:null,compare:null,initialize:function(yOrdering){this.compare=yOrdering?OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_Y_ORDER:OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_DRAWING_ORDER;this.clear();},insert:function(newNode){if(this.exists(newNode)){this.remove(newNode);}
+var nodeId=newNode.id;this.determineZIndex(newNode);var leftIndex=-1;var rightIndex=this.order.length;var middle;while(rightIndex-leftIndex>1){middle=parseInt((leftIndex+rightIndex)/2);var placement=this.compare(this,newNode,OpenLayers.Util.getElement(this.order[middle]));if(placement>0){leftIndex=middle;}else{rightIndex=middle;}}
+this.order.splice(rightIndex,0,nodeId);this.indices[nodeId]=this.getZIndex(newNode);return this.getNextElement(rightIndex);},remove:function(node){var nodeId=node.id;var arrayIndex=OpenLayers.Util.indexOf(this.order,nodeId);if(arrayIndex>=0){this.order.splice(arrayIndex,1);delete this.indices[nodeId];if(this.order.length>0){var lastId=this.order[this.order.length-1];this.maxZIndex=this.indices[lastId];}else{this.maxZIndex=0;}}},clear:function(){this.order=[];this.indices={};this.maxZIndex=0;},exists:function(node){return(this.indices[node.id]!=null);},getZIndex:function(node){return node._style.graphicZIndex;},determineZIndex:function(node){var zIndex=node._style.graphicZIndex;if(zIndex==null){zIndex=this.maxZIndex;node._style.graphicZIndex=zIndex;}else if(zIndex>this.maxZIndex){this.maxZIndex=zIndex;}},getNextElement:function(index){var nextIndex=index+1;if(nextIndex<this.order.length){var nextElement=OpenLayers.Util.getElement(this.order[nextIndex]);if(nextElement==undefined){nextElement=this.getNextElement(nextIndex);}
+return nextElement;}else{return null;}},CLASS_NAME:"OpenLayers.ElementsIndexer"});OpenLayers.ElementsIndexer.IndexingMethods={Z_ORDER:function(indexer,newNode,nextNode){var newZIndex=indexer.getZIndex(newNode);var returnVal=0;if(nextNode){var nextZIndex=indexer.getZIndex(nextNode);returnVal=newZIndex-nextZIndex;}
+return returnVal;},Z_ORDER_DRAWING_ORDER:function(indexer,newNode,nextNode){var returnVal=OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(indexer,newNode,nextNode);if(nextNode&&returnVal==0){returnVal=1;}
+return returnVal;},Z_ORDER_Y_ORDER:function(indexer,newNode,nextNode){var returnVal=OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(indexer,newNode,nextNode);if(nextNode&&returnVal===0){var result=nextNode._boundsBottom-newNode._boundsBottom;returnVal=(result===0)?1:result;}
+return returnVal;}};OpenLayers.Renderer.Elements=OpenLayers.Class(OpenLayers.Renderer,{rendererRoot:null,root:null,vectorRoot:null,textRoot:null,xmlns:null,xOffset:0,indexer:null,BACKGROUND_ID_SUFFIX:"_background",LABEL_ID_SUFFIX:"_label",LABEL_OUTLINE_SUFFIX:"_outline",initialize:function(containerID,options){OpenLayers.Renderer.prototype.initialize.apply(this,arguments);this.rendererRoot=this.createRenderRoot();this.root=this.createRoot("_root");this.vectorRoot=this.createRoot("_vroot");this.textRoot=this.createRoot("_troot");this.root.appendChild(this.vectorRoot);this.root.appendChild(this.textRoot);this.rendererRoot.appendChild(this.root);this.container.appendChild(this.rendererRoot);if(options&&(options.zIndexing||options.yOrdering)){this.indexer=new OpenLayers.ElementsIndexer(options.yOrdering);}},destroy:function(){this.clear();this.rendererRoot=null;this.root=null;this.xmlns=null;OpenLayers.Renderer.prototype.destroy.apply(this,arguments);},clear:function(){var child;var root=this.vectorRoot;if(root){while(child=root.firstChild){root.removeChild(child);}}
+root=this.textRoot;if(root){while(child=root.firstChild){root.removeChild(child);}}
+if(this.indexer){this.indexer.clear();}},setExtent:function(extent,resolutionChanged){var coordSysUnchanged=OpenLayers.Renderer.prototype.setExtent.apply(this,arguments);var resolution=this.getResolution();if(this.map.baseLayer&&this.map.baseLayer.wrapDateLine){var rightOfDateLine,ratio=extent.getWidth()/this.map.getExtent().getWidth(),extent=extent.scale(1/ratio),world=this.map.getMaxExtent();if(world.right>extent.left&&world.right<extent.right){rightOfDateLine=true;}else if(world.left>extent.left&&world.left<extent.right){rightOfDateLine=false;}
+if(rightOfDateLine!==this.rightOfDateLine||resolutionChanged){coordSysUnchanged=false;this.xOffset=rightOfDateLine===true?world.getWidth()/resolution:0;}
+this.rightOfDateLine=rightOfDateLine;}
+return coordSysUnchanged;},getNodeType:function(geometry,style){},drawGeometry:function(geometry,style,featureId){var className=geometry.CLASS_NAME;var rendered=true;if((className=="OpenLayers.Geometry.Collection")||(className=="OpenLayers.Geometry.MultiPoint")||(className=="OpenLayers.Geometry.MultiLineString")||(className=="OpenLayers.Geometry.MultiPolygon")){for(var i=0,len=geometry.components.length;i<len;i++){rendered=this.drawGeometry(geometry.components[i],style,featureId)&&rendered;}
+return rendered;}
+rendered=false;var removeBackground=false;if(style.display!="none"){if(style.backgroundGraphic){this.redrawBackgroundNode(geometry.id,geometry,style,featureId);}else{removeBackground=true;}
+rendered=this.redrawNode(geometry.id,geometry,style,featureId);}
+if(rendered==false){var node=document.getElementById(geometry.id);if(node){if(node._style.backgroundGraphic){removeBackground=true;}
+node.parentNode.removeChild(node);}}
+if(removeBackground){var node=document.getElementById(geometry.id+this.BACKGROUND_ID_SUFFIX);if(node){node.parentNode.removeChild(node);}}
+return rendered;},redrawNode:function(id,geometry,style,featureId){style=this.applyDefaultSymbolizer(style);var node=this.nodeFactory(id,this.getNodeType(geometry,style));node._featureId=featureId;node._boundsBottom=geometry.getBounds().bottom;node._geometryClass=geometry.CLASS_NAME;node._style=style;var drawResult=this.drawGeometryNode(node,geometry,style);if(drawResult===false){return false;}
+node=drawResult.node;if(this.indexer){var insert=this.indexer.insert(node);if(insert){this.vectorRoot.insertBefore(node,insert);}else{this.vectorRoot.appendChild(node);}}else{if(node.parentNode!==this.vectorRoot){this.vectorRoot.appendChild(node);}}
+this.postDraw(node);return drawResult.complete;},redrawBackgroundNode:function(id,geometry,style,featureId){var backgroundStyle=OpenLayers.Util.extend({},style);backgroundStyle.externalGraphic=backgroundStyle.backgroundGraphic;backgroundStyle.graphicXOffset=backgroundStyle.backgroundXOffset;backgroundStyle.graphicYOffset=backgroundStyle.backgroundYOffset;backgroundStyle.graphicZIndex=backgroundStyle.backgroundGraphicZIndex;backgroundStyle.graphicWidth=backgroundStyle.backgroundWidth||backgroundStyle.graphicWidth;backgroundStyle.graphicHeight=backgroundStyle.backgroundHeight||backgroundStyle.graphicHeight;backgroundStyle.backgroundGraphic=null;backgroundStyle.backgroundXOffset=null;backgroundStyle.backgroundYOffset=null;backgroundStyle.backgroundGraphicZIndex=null;return this.redrawNode(id+this.BACKGROUND_ID_SUFFIX,geometry,backgroundStyle,null);},drawGeometryNode:function(node,geometry,style){style=style||node._style;var options={'isFilled':style.fill===undefined?true:style.fill,'isStroked':style.stroke===undefined?!!style.strokeWidth:style.stroke};var drawn;switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":if(style.graphic===false){options.isFilled=false;options.isStroked=false;}
+drawn=this.drawPoint(node,geometry);break;case"OpenLayers.Geometry.LineString":options.isFilled=false;drawn=this.drawLineString(node,geometry);break;case"OpenLayers.Geometry.LinearRing":drawn=this.drawLinearRing(node,geometry);break;case"OpenLayers.Geometry.Polygon":drawn=this.drawPolygon(node,geometry);break;case"OpenLayers.Geometry.Rectangle":drawn=this.drawRectangle(node,geometry);break;default:break;}
+node._options=options;if(drawn!=false){return{node:this.setStyle(node,style,options,geometry),complete:drawn};}else{return false;}},postDraw:function(node){},drawPoint:function(node,geometry){},drawLineString:function(node,geometry){},drawLinearRing:function(node,geometry){},drawPolygon:function(node,geometry){},drawRectangle:function(node,geometry){},drawCircle:function(node,geometry){},removeText:function(featureId){var label=document.getElementById(featureId+this.LABEL_ID_SUFFIX);if(label){this.textRoot.removeChild(label);}
+var outline=document.getElementById(featureId+this.LABEL_OUTLINE_SUFFIX);if(outline){this.textRoot.removeChild(outline);}},getFeatureIdFromEvent:function(evt){var target=evt.target;var useElement=target&&target.correspondingUseElement;var node=useElement?useElement:(target||evt.srcElement);return node._featureId;},eraseGeometry:function(geometry,featureId){if((geometry.CLASS_NAME=="OpenLayers.Geometry.MultiPoint")||(geometry.CLASS_NAME=="OpenLayers.Geometry.MultiLineString")||(geometry.CLASS_NAME=="OpenLayers.Geometry.MultiPolygon")||(geometry.CLASS_NAME=="OpenLayers.Geometry.Collection")){for(var i=0,len=geometry.components.length;i<len;i++){this.eraseGeometry(geometry.components[i],featureId);}}else{var element=OpenLayers.Util.getElement(geometry.id);if(element&&element.parentNode){if(element.geometry){element.geometry.destroy();element.geometry=null;}
+element.parentNode.removeChild(element);if(this.indexer){this.indexer.remove(element);}
+if(element._style.backgroundGraphic){var backgroundId=geometry.id+this.BACKGROUND_ID_SUFFIX;var bElem=OpenLayers.Util.getElement(backgroundId);if(bElem&&bElem.parentNode){bElem.parentNode.removeChild(bElem);}}}}},nodeFactory:function(id,type){var node=OpenLayers.Util.getElement(id);if(node){if(!this.nodeTypeCompare(node,type)){node.parentNode.removeChild(node);node=this.nodeFactory(id,type);}}else{node=this.createNode(type,id);}
+return node;},nodeTypeCompare:function(node,type){},createNode:function(type,id){},moveRoot:function(renderer){var root=this.root;if(renderer.root.parentNode==this.rendererRoot){root=renderer.root;}
+root.parentNode.removeChild(root);renderer.rendererRoot.appendChild(root);},getRenderLayerId:function(){return this.root.parentNode.parentNode.id;},isComplexSymbol:function(graphicName){return(graphicName!="circle")&&!!graphicName;},CLASS_NAME:"OpenLayers.Renderer.Elements"});OpenLayers.Lang["sv"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Ej hanterad fråga retur ${statusText}",'Permalink':"Permalänk",'Overlays':"Kartlager",'Base Layer':"Bakgrundskarta",'noFID':"Kan ej uppdatera feature (objekt) för vilket FID saknas.",'browserNotSupported':"Din webbläsare stöder inte vektorvisning. För närvarande stöds följande visning:\n${renderers}",'minZoomLevelError':"Egenskapen minZoomLevel är endast avsedd att användas med lager med FixedZoomLevels. Att detta WFS-lager kontrollerar minZoomLevel är en relik från äldre versioner. Vi kan dock inte ta bort det utan att riskera att OL-baserade tillämpningar som använder detta slutar fungera. Därför är det satt som deprecated, minZoomLevel kommer att tas bort i version 3.0. Använd i stället inställning av min/max resolution som beskrivs här: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-transaktion: LYCKADES ${response}",'commitFailed':"WFS-transaktion: MISSLYCKADES ${response}",'googleWarning':"Google-lagret kunde inte laddas korrekt.\x3cbr\x3e\x3cbr\x3eFör att slippa detta meddelande, välj en annan bakgrundskarta i lagerväljaren i övre högra hörnet.\x3cbr\x3e\x3cbr\x3eSannolikt beror felet på att Google Maps-biblioteket inte är inkluderat på webbsidan eller på att sidan inte anger korrekt API-nyckel för webbplatsen.\x3cbr\x3e\x3cbr\x3eUtvecklare: hjälp för att åtgärda detta, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eklicka här\x3c/a\x3e.",'getLayerWarning':"${layerType}-lagret kunde inte laddas korrekt.\x3cbr\x3e\x3cbr\x3eFör att slippa detta meddelande, välj en annan bakgrundskarta i lagerväljaren i övre högra hörnet.\x3cbr\x3e\x3cbr\x3eSannolikt beror felet på att ${layerLib}-biblioteket inte är inkluderat på webbsidan.\x3cbr\x3e\x3cbr\x3eUtvecklare: hjälp för att åtgärda detta, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eklicka här\x3c/a\x3e.",'Scale = 1 : ${scaleDenom}':"\x3cstrong\x3eSkala\x3c/strong\x3e 1 : ${scaleDenom}",'reprojectDeprecated':"Du använder inställningen \'reproject\' på lagret ${layerName}. Denna inställning markerad som deprecated: den var avsedd att användas för att stödja visning av kartdata på kommersiella bakgrundskartor, men nu bör man i stället använda Spherical Mercator-stöd för den funktionaliteten. Mer information finns på http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Denna metod är markerad som deprecated och kommer att tas bort i 3.0. Använd ${newMethod} i stället."});OpenLayers.Strategy=OpenLayers.Class({layer:null,options:null,active:null,autoActivate:true,autoDestroy:true,initialize:function(options){OpenLayers.Util.extend(this,options);this.options=options;this.active=false;},destroy:function(){this.deactivate();this.layer=null;this.options=null;},setLayer:function(layer){this.layer=layer;},activate:function(){if(!this.active){this.active=true;return true;}
+return false;},deactivate:function(){if(this.active){this.active=false;return true;}
+return false;},CLASS_NAME:"OpenLayers.Strategy"});OpenLayers.Strategy.Fixed=OpenLayers.Class(OpenLayers.Strategy,{preload:false,activate:function(){if(OpenLayers.Strategy.prototype.activate.apply(this,arguments)){this.layer.events.on({"refresh":this.load,scope:this});if(this.layer.visibility==true||this.preload){this.load();}else{this.layer.events.on({"visibilitychanged":this.load,scope:this});}
+return true;}
+return false;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.layer.events.un({"refresh":this.load,"visibilitychanged":this.load,scope:this});}
+return deactivated;},load:function(options){var layer=this.layer;layer.events.triggerEvent("loadstart");layer.protocol.read(OpenLayers.Util.applyDefaults({callback:OpenLayers.Function.bind(this.merge,this,layer.map.getProjectionObject()),filter:layer.filter},options));layer.events.un({"visibilitychanged":this.load,scope:this});},merge:function(mapProjection,resp){var layer=this.layer;layer.destroyFeatures();var features=resp.features;if(features&&features.length>0){if(!mapProjection.equals(layer.projection)){var geom;for(var i=0,len=features.length;i<len;++i){geom=features[i].geometry;if(geom){geom.transform(layer.projection,mapProjection);}}}
+layer.addFeatures(features);}
+layer.events.triggerEvent("loadend");},CLASS_NAME:"OpenLayers.Strategy.Fixed"});OpenLayers.Layer.Markers=OpenLayers.Class(OpenLayers.Layer,{isBaseLayer:false,markers:null,drawn:false,initialize:function(name,options){OpenLayers.Layer.prototype.initialize.apply(this,arguments);this.markers=[];},destroy:function(){this.clearMarkers();this.markers=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},setOpacity:function(opacity){if(opacity!=this.opacity){this.opacity=opacity;for(var i=0,len=this.markers.length;i<len;i++){this.markers[i].setOpacity(this.opacity);}}},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);if(zoomChanged||!this.drawn){for(var i=0,len=this.markers.length;i<len;i++){this.drawMarker(this.markers[i]);}
+this.drawn=true;}},addMarker:function(marker){this.markers.push(marker);if(this.opacity<1){marker.setOpacity(this.opacity);}
+if(this.map&&this.map.getExtent()){marker.map=this.map;this.drawMarker(marker);}},removeMarker:function(marker){if(this.markers&&this.markers.length){OpenLayers.Util.removeItem(this.markers,marker);marker.erase();}},clearMarkers:function(){if(this.markers!=null){while(this.markers.length>0){this.removeMarker(this.markers[0]);}}},drawMarker:function(marker){var px=this.map.getLayerPxFromLonLat(marker.lonlat);if(px==null){marker.display(false);}else{if(!marker.isDrawn()){var markerImg=marker.draw(px);this.div.appendChild(markerImg);}else if(marker.icon){marker.icon.moveTo(px);}}},getDataExtent:function(){var maxExtent=null;if(this.markers&&(this.markers.length>0)){var maxExtent=new OpenLayers.Bounds();for(var i=0,len=this.markers.length;i<len;i++){var marker=this.markers[i];maxExtent.extend(marker.lonlat);}}
+return maxExtent;},CLASS_NAME:"OpenLayers.Layer.Markers"});OpenLayers.Control.Zoom=OpenLayers.Class(OpenLayers.Control,{zoomInText:"+",zoomInId:"olZoomInLink",zoomOutText:"-",zoomOutId:"olZoomOutLink",draw:function(){var div=OpenLayers.Control.prototype.draw.apply(this),links=this.getOrCreateLinks(div),zoomIn=links.zoomIn,zoomOut=links.zoomOut,eventsInstance=this.map.events;if(zoomOut.parentNode!==div){eventsInstance=this.events;eventsInstance.attachToElement(zoomOut.parentNode);}
+eventsInstance.register("buttonclick",this,this.onZoomClick);this.zoomInLink=zoomIn;this.zoomOutLink=zoomOut;return div;},getOrCreateLinks:function(el){var zoomIn=document.getElementById(this.zoomInId),zoomOut=document.getElementById(this.zoomOutId);if(!zoomIn){zoomIn=document.createElement("a");zoomIn.href="#zoomIn";zoomIn.appendChild(document.createTextNode(this.zoomInText));zoomIn.className="olControlZoomIn";el.appendChild(zoomIn);}
+OpenLayers.Element.addClass(zoomIn,"olButton");if(!zoomOut){zoomOut=document.createElement("a");zoomOut.href="#zoomOut";zoomOut.appendChild(document.createTextNode(this.zoomOutText));zoomOut.className="olControlZoomOut";el.appendChild(zoomOut);}
+OpenLayers.Element.addClass(zoomOut,"olButton");return{zoomIn:zoomIn,zoomOut:zoomOut};},onZoomClick:function(evt){var button=evt.buttonElement;if(button===this.zoomInLink){this.map.zoomIn();}else if(button===this.zoomOutLink){this.map.zoomOut();}},destroy:function(){if(this.map){this.map.events.unregister("buttonclick",this,this.onZoomClick);}
+delete this.zoomInLink;delete this.zoomOutLink;OpenLayers.Control.prototype.destroy.apply(this);},CLASS_NAME:"OpenLayers.Control.Zoom"});OpenLayers.Lang.it={'unhandledRequest':"Codice di ritorno della richiesta ${statusText}",'Permalink':"Permalink",'Overlays':"Overlays",'Base Layer':"Livello base",'noFID':"Impossibile aggiornare un elemento grafico che non abbia il FID.",'browserNotSupported':"Il tuo browser non supporta il rendering vettoriale. I renderizzatore attualemnte supportati sono:\n${renderers}",'minZoomLevelError':"La proprietà minZoomLevel è da utilizzare solamente "+"con livelli che abbiano FixedZoomLevels. Il fatto che "+"questo livello wfs controlli la proprietà minZoomLevel è "+"un retaggio del passato. Non possiamo comunque rimuoverla "+"senza rompere le vecchie applicazioni che dipendono su di essa."+"Quindi siamo costretti a deprecarla -- minZoomLevel "+"e sarà rimossa dalla vesione 3.0. Si prega di utilizzare i "+"settaggi di risoluzione min/max come descritto qui: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transazione WFS: SUCCESS ${response}",'commitFailed':"Transazione WFS: FAILED ${response}",'googleWarning':"Il livello Google non è riuscito a caricare correttamente.<br><br>"+"Per evitare questo messaggio, seleziona un nuovo BaseLayer "+"nel selettore di livelli nell'angolo in alto a destra.<br><br>"+"Più precisamente, ciò accade perchè la libreria Google Maps "+"non è stata inclusa nella pagina, oppure non contiene la "+"corretta API key per il tuo sito.<br><br>"+"Sviluppatori: Per aiuto su come farlo funzionare correttamente, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>clicca qui</a>",'getLayerWarning':"Il livello ${layerType} non è riuscito a caricare correttamente.<br><br>"+"Per evitare questo messaggio, seleziona un nuovo BaseLayer "+"nel selettore di livelli nell'angolo in alto a destra.<br><br>"+"Più precisamente, ciò accade perchè la libreria ${layerLib} "+"non è stata inclusa nella pagina.<br><br>"+"Sviluppatori: Per aiuto su come farlo funzionare correttamente, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>clicca qui</a>",'Scale = 1 : ${scaleDenom}':"Scala = 1 : ${scaleDenom}",'reprojectDeprecated':"Stai utilizzando l'opzione 'reproject' sul livello ${layerName}. "+"Questa opzione è deprecata: il suo utilizzo è stato introdotto per"+"supportare il disegno dei dati sopra mappe commerciali, ma tale "+"funzionalità dovrebbe essere ottenuta tramite l'utilizzo della proiezione "+"Spherical Mercator. Per maggiori informazioni consultare qui "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Questo metodo è stato deprecato e sarà rimosso dalla versione 3.0. "+"Si prega di utilizzare il metodo ${newMethod} in alternativa.",'end':''};OpenLayers.Lang["oc"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Requèsta pas gerida, retorna ${statusText}",'Permalink':"Permaligam",'Overlays':"Calques",'Base Layer':"Calc de basa",'noFID':"Impossible de metre a jorn un objècte sens identificant (fid).",'browserNotSupported':"Vòstre navegidor supòrta pas lo rendut vectorial. Los renderers actualament suportats son : \n${renderers}",'minZoomLevelError':"La proprietat minZoomLevel deu èsser utilizada solament per de jaces FixedZoomLevels-descendent. Lo fach qu\'aqueste jaç WFS verifique la preséncia de minZoomLevel es una relica del passat. Çaquelà, la podèm suprimir sens copar d\'aplicacions que ne poirián dependre. Es per aquò que la depreciam -- la verificacion del minZoomLevel serà suprimida en version 3.0. A la plaça, mercés d\'utilizar los paramètres de resolucions min/max tal coma descrich sus : http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transaccion WFS : SUCCES ${response}",'commitFailed':"Transaccion WFS : FRACAS ${response}",'googleWarning':"Lo jaç Google es pas estat en mesura de se cargar corrèctament.\x3cbr\x3e\x3cbr\x3ePer suprimir aqueste messatge, causissètz una BaseLayer novèla dins lo selector de jaç en naut a drecha.\x3cbr\x3e\x3cbr\x3eAquò es possiblament causat par la non-inclusion de la librariá Google Maps, o alara perque que la clau de l\'API correspond pas a vòstre site.\x3cbr\x3e\x3cbr\x3eDesvolopaires : per saber cossí corregir aquò, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclicatz aicí\x3c/a\x3e",'getLayerWarning':"Lo jaç ${layerType} es pas en mesura de se cargar corrèctament.\x3cbr\x3e\x3cbr\x3ePer suprimir aqueste messatge, causissètz una  BaseLayer novèla dins lo selector de jaç en naut a drecha.\x3cbr\x3e\x3cbr\x3eAquò es possiblament causat per la non-inclusion de la librariá ${layerLib}.\x3cbr\x3e\x3cbr\x3eDesvolopaires : per saber cossí corregir aquí, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclicatz aicí\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Escala ~ 1 : ${scaleDenom}",'W':"O",'E':"È",'N':"N",'S':"S",'reprojectDeprecated':"Utilizatz l\'opcion \'reproject\' sul jaç ${layerName}. Aquesta opcion es despreciada : Son usatge permetiá d\'afichar de donadas al dessús de jaces raster comercials. Aquesta foncionalitat ara es suportada en utilizant lo supòrt de la projeccion Mercator Esferica. Mai d\'informacion es disponibla sus http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Aqueste metòde es despreciada, e serà suprimida a la version 3.0. Mercés d\'utilizar ${newMethod} a la plaça."});OpenLayers.Lang["gsw"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nit behandleti Aafrogsruckmäldig ${statusText}",'Permalink':"Permalink",'Overlays':"Iberlagerige",'Base Layer':"Grundcharte",'noFID':"E Feature, wu s kei FID derfir git, cha nit aktualisiert wäre.",'browserNotSupported':"Dyy Browser unterstitzt kei Vektordarstellig. Aktuäll unterstitzti Renderer:\n${renderers}",'minZoomLevelError':"D minZoomLevel-Eigeschaft isch nume dänk fir d Layer, wu vu dr FixedZoomLevels abstamme. Ass dää wfs-Layer minZoomLevel prieft, scih e Relikt us dr Vergangeheit. Mir chenne s aber nit ändere ohni OL_basierti Aawändige villicht kaputt gehn, wu dervu abhänge.  Us däm Grund het die Funktion d Eigeschaft \'deprecated\' iberchuu. D minZoomLevel-Priefig unte wird in dr Version 3.0 usegnuu. Bitte verwänd statt däm e min/max-Uflesig wie s do bschriben isch: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-Transaktion: ERFOLGRYCH ${response}",'commitFailed':"WFS-Transaktion: FÄHLGSCHLAA ${response}",'googleWarning':"Dr Google-Layer het nit korräkt chenne glade wäre.\x3cbr\x3e\x3cbr\x3eGo die Mäldig nimi z kriege, wehl e andere Hintergrundlayer us em LayerSwitcher im rächte obere Ecke.\x3cbr\x3e\x3cbr\x3eDää Fähler git s seli hyfig, wel s Skript vu dr Google-Maps-Bibliothek nit yybunde woren isch oder wel s kei giltige API-Schlissel fir Dyy URL din het.\x3cbr\x3e\x3cbr\x3eEntwickler: Fir Hilf zum korräkte Yybinde vum Google-Layer \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3edoo drucke\x3c/a\x3e",'getLayerWarning':"Dr ${layerType}-Layer het nit korräkt chenne glade wäre.\x3cbr\x3e\x3cbr\x3eGo die Mäldig nimi z kriege, wehl e andere Hintergrundlayer us em LayerSwitcher im rächte obere Ecke.\x3cbr\x3e\x3cbr\x3eDää Fähler git s seli hyfig, wel s Skript vu dr \'${layerLib}\'-Bibliothek nit yybunde woren isch oder wel s kei giltige API-Schlissel fir Dyy URL din het.\x3cbr\x3e\x3cbr\x3eEntwickler: Fir Hilf zum korräkte Yybinde vu Layer \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3edoo drucke\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Maßstab = 1 : ${scaleDenom}",'W':"W",'E':"O",'N':"N",'S':"S",'reprojectDeprecated':"Du bruchsch d \'reproject\'-Option bim ${layerName}-Layer. Die Option isch nimi giltig: si isch aagleit wore go   Date iber kommerziälli Grundcharte lege, aber des sott mer jetz mache mit dr Unterstitzig vu Spherical Mercator. Meh Informatione git s uf http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Die Methode isch veraltet un wird us dr Version 3.0 usegnuu. Bitte verwäbnd statt däm ${newMethod}."});OpenLayers.Geometry.MultiPolygon=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.Polygon"],CLASS_NAME:"OpenLayers.Geometry.MultiPolygon"});OpenLayers.Style=OpenLayers.Class({id:null,name:null,title:null,description:null,layerName:null,isDefault:false,rules:null,context:null,defaultStyle:null,defaultsPerSymbolizer:false,propertyStyles:null,initialize:function(style,options){OpenLayers.Util.extend(this,options);this.rules=[];if(options&&options.rules){this.addRules(options.rules);}
+this.setDefaultStyle(style||OpenLayers.Feature.Vector.style["default"]);this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){for(var i=0,len=this.rules.length;i<len;i++){this.rules[i].destroy();this.rules[i]=null;}
+this.rules=null;this.defaultStyle=null;},createSymbolizer:function(feature){var style=this.defaultsPerSymbolizer?{}:this.createLiterals(OpenLayers.Util.extend({},this.defaultStyle),feature);var rules=this.rules;var rule,context;var elseRules=[];var appliedRules=false;for(var i=0,len=rules.length;i<len;i++){rule=rules[i];var applies=rule.evaluate(feature);if(applies){if(rule instanceof OpenLayers.Rule&&rule.elseFilter){elseRules.push(rule);}else{appliedRules=true;this.applySymbolizer(rule,style,feature);}}}
+if(appliedRules==false&&elseRules.length>0){appliedRules=true;for(var i=0,len=elseRules.length;i<len;i++){this.applySymbolizer(elseRules[i],style,feature);}}
+if(rules.length>0&&appliedRules==false){style.display="none";}
+if(style.label!=null&&typeof style.label!=="string"){style.label=String(style.label);}
+return style;},applySymbolizer:function(rule,style,feature){var symbolizerPrefix=feature.geometry?this.getSymbolizerPrefix(feature.geometry):OpenLayers.Style.SYMBOLIZER_PREFIXES[0];var symbolizer=rule.symbolizer[symbolizerPrefix]||rule.symbolizer;if(this.defaultsPerSymbolizer===true){var defaults=this.defaultStyle;OpenLayers.Util.applyDefaults(symbolizer,{pointRadius:defaults.pointRadius});if(symbolizer.stroke===true||symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{strokeWidth:defaults.strokeWidth,strokeColor:defaults.strokeColor,strokeOpacity:defaults.strokeOpacity,strokeDashstyle:defaults.strokeDashstyle,strokeLinecap:defaults.strokeLinecap});}
+if(symbolizer.fill===true||symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{fillColor:defaults.fillColor,fillOpacity:defaults.fillOpacity});}
+if(symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{pointRadius:this.defaultStyle.pointRadius,externalGraphic:this.defaultStyle.externalGraphic,graphicName:this.defaultStyle.graphicName,graphicOpacity:this.defaultStyle.graphicOpacity,graphicWidth:this.defaultStyle.graphicWidth,graphicHeight:this.defaultStyle.graphicHeight,graphicXOffset:this.defaultStyle.graphicXOffset,graphicYOffset:this.defaultStyle.graphicYOffset});}}
+return this.createLiterals(OpenLayers.Util.extend(style,symbolizer),feature);},createLiterals:function(style,feature){var context=OpenLayers.Util.extend({},feature.attributes||feature.data);OpenLayers.Util.extend(context,this.context);for(var i in this.propertyStyles){style[i]=OpenLayers.Style.createLiteral(style[i],context,feature,i);}
+return style;},findPropertyStyles:function(){var propertyStyles={};var style=this.defaultStyle;this.addPropertyStyles(propertyStyles,style);var rules=this.rules;var symbolizer,value;for(var i=0,len=rules.length;i<len;i++){symbolizer=rules[i].symbolizer;for(var key in symbolizer){value=symbolizer[key];if(typeof value=="object"){this.addPropertyStyles(propertyStyles,value);}else{this.addPropertyStyles(propertyStyles,symbolizer);break;}}}
+return propertyStyles;},addPropertyStyles:function(propertyStyles,symbolizer){var property;for(var key in symbolizer){property=symbolizer[key];if(typeof property=="string"&&property.match(/\$\{\w+\}/)){propertyStyles[key]=true;}}
+return propertyStyles;},addRules:function(rules){Array.prototype.push.apply(this.rules,rules);this.propertyStyles=this.findPropertyStyles();},setDefaultStyle:function(style){this.defaultStyle=style;this.propertyStyles=this.findPropertyStyles();},getSymbolizerPrefix:function(geometry){var prefixes=OpenLayers.Style.SYMBOLIZER_PREFIXES;for(var i=0,len=prefixes.length;i<len;i++){if(geometry.CLASS_NAME.indexOf(prefixes[i])!=-1){return prefixes[i];}}},clone:function(){var options=OpenLayers.Util.extend({},this);if(this.rules){options.rules=[];for(var i=0,len=this.rules.length;i<len;++i){options.rules.push(this.rules[i].clone());}}
+options.context=this.context&&OpenLayers.Util.extend({},this.context);var defaultStyle=OpenLayers.Util.extend({},this.defaultStyle);return new OpenLayers.Style(defaultStyle,options);},CLASS_NAME:"OpenLayers.Style"});OpenLayers.Style.createLiteral=function(value,context,feature,property){if(typeof value=="string"&&value.indexOf("${")!=-1){value=OpenLayers.String.format(value,context,[feature,property]);value=(isNaN(value)||!value)?value:parseFloat(value);}
+return value;};OpenLayers.Style.SYMBOLIZER_PREFIXES=['Point','Line','Polygon','Text','Raster'];OpenLayers.Filter=OpenLayers.Class({initialize:function(options){OpenLayers.Util.extend(this,options);},destroy:function(){},evaluate:function(context){return true;},clone:function(){return null;},toString:function(){var string;if(OpenLayers.Format&&OpenLayers.Format.CQL){string=OpenLayers.Format.CQL.prototype.write(this);}else{string=Object.prototype.toString.call(this);}
+return string;},CLASS_NAME:"OpenLayers.Filter"});OpenLayers.Filter.Spatial=OpenLayers.Class(OpenLayers.Filter,{type:null,property:null,value:null,distance:null,distanceUnits:null,evaluate:function(feature){var intersect=false;switch(this.type){case OpenLayers.Filter.Spatial.BBOX:case OpenLayers.Filter.Spatial.INTERSECTS:if(feature.geometry){var geom=this.value;if(this.value.CLASS_NAME=="OpenLayers.Bounds"){geom=this.value.toGeometry();}
+if(feature.geometry.intersects(geom)){intersect=true;}}
+break;default:throw new Error('evaluate is not implemented for this filter type.');}
+return intersect;},clone:function(){var options=OpenLayers.Util.applyDefaults({value:this.value&&this.value.clone&&this.value.clone()},this);return new OpenLayers.Filter.Spatial(options);},CLASS_NAME:"OpenLayers.Filter.Spatial"});OpenLayers.Filter.Spatial.BBOX="BBOX";OpenLayers.Filter.Spatial.INTERSECTS="INTERSECTS";OpenLayers.Filter.Spatial.DWITHIN="DWITHIN";OpenLayers.Filter.Spatial.WITHIN="WITHIN";OpenLayers.Filter.Spatial.CONTAINS="CONTAINS";OpenLayers.Strategy.BBOX=OpenLayers.Class(OpenLayers.Strategy,{bounds:null,resolution:null,ratio:2,resFactor:null,response:null,activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){this.layer.events.on({"moveend":this.update,"refresh":this.update,"visibilitychanged":this.update,scope:this});this.update();}
+return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.layer.events.un({"moveend":this.update,"refresh":this.update,"visibilitychanged":this.update,scope:this});}
+return deactivated;},update:function(options){var mapBounds=this.getMapBounds();if(mapBounds!==null&&((options&&options.force)||(this.layer.visibility&&this.layer.calculateInRange()&&this.invalidBounds(mapBounds)))){this.calculateBounds(mapBounds);this.resolution=this.layer.map.getResolution();this.triggerRead(options);}},getMapBounds:function(){if(this.layer.map===null){return null;}
+var bounds=this.layer.map.getExtent();if(bounds&&!this.layer.projection.equals(this.layer.map.getProjectionObject())){bounds=bounds.clone().transform(this.layer.map.getProjectionObject(),this.layer.projection);}
+return bounds;},invalidBounds:function(mapBounds){if(!mapBounds){mapBounds=this.getMapBounds();}
+var invalid=!this.bounds||!this.bounds.containsBounds(mapBounds);if(!invalid&&this.resFactor){var ratio=this.resolution/this.layer.map.getResolution();invalid=(ratio>=this.resFactor||ratio<=(1/this.resFactor));}
+return invalid;},calculateBounds:function(mapBounds){if(!mapBounds){mapBounds=this.getMapBounds();}
+var center=mapBounds.getCenterLonLat();var dataWidth=mapBounds.getWidth()*this.ratio;var dataHeight=mapBounds.getHeight()*this.ratio;this.bounds=new OpenLayers.Bounds(center.lon-(dataWidth/2),center.lat-(dataHeight/2),center.lon+(dataWidth/2),center.lat+(dataHeight/2));},triggerRead:function(options){if(this.response&&!(options&&options.noAbort===true)){this.layer.protocol.abort(this.response);this.layer.events.triggerEvent("loadend");}
+this.layer.events.triggerEvent("loadstart");this.response=this.layer.protocol.read(OpenLayers.Util.applyDefaults({filter:this.createFilter(),callback:this.merge,scope:this},options));},createFilter:function(){var filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.BBOX,value:this.bounds,projection:this.layer.projection});if(this.layer.filter){filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND,filters:[this.layer.filter,filter]});}
+return filter;},merge:function(resp){this.layer.destroyFeatures();if(resp.code==OpenLayers.Protocol.Response.SUCCESS){var features=resp.features;if(features&&features.length>0){var remote=this.layer.projection;var local=this.layer.map.getProjectionObject();if(!local.equals(remote)){var geom;for(var i=0,len=features.length;i<len;++i){geom=features[i].geometry;if(geom){geom.transform(remote,local);}}}
+this.layer.addFeatures(features);}}else{this.bounds=null;}
+this.response=null;this.layer.events.triggerEvent("loadend");},CLASS_NAME:"OpenLayers.Strategy.BBOX"});OpenLayers.Handler.Feature=OpenLayers.Class(OpenLayers.Handler,{EVENTMAP:{'click':{'in':'click','out':'clickout'},'mousemove':{'in':'over','out':'out'},'dblclick':{'in':'dblclick','out':null},'mousedown':{'in':null,'out':null},'mouseup':{'in':null,'out':null},'touchstart':{'in':'click','out':'clickout'}},feature:null,lastFeature:null,down:null,up:null,touch:false,clickTolerance:4,geometryTypes:null,stopClick:true,stopDown:true,stopUp:false,initialize:function(control,layer,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,[control,callbacks,options]);this.layer=layer;},touchstart:function(evt){if(!this.touch){this.touch=true;this.map.events.un({mousedown:this.mousedown,mouseup:this.mouseup,mousemove:this.mousemove,click:this.click,dblclick:this.dblclick,scope:this});}
+return OpenLayers.Event.isMultiTouch(evt)?true:this.mousedown(evt);},touchmove:function(evt){OpenLayers.Event.stop(evt);},mousedown:function(evt){if(OpenLayers.Event.isLeftClick(evt)||OpenLayers.Event.isSingleTouch(evt)){this.down=evt.xy;}
+return this.handle(evt)?!this.stopDown:true;},mouseup:function(evt){this.up=evt.xy;return this.handle(evt)?!this.stopUp:true;},click:function(evt){return this.handle(evt)?!this.stopClick:true;},mousemove:function(evt){if(!this.callbacks['over']&&!this.callbacks['out']){return true;}
+this.handle(evt);return true;},dblclick:function(evt){return!this.handle(evt);},geometryTypeMatches:function(feature){return this.geometryTypes==null||OpenLayers.Util.indexOf(this.geometryTypes,feature.geometry.CLASS_NAME)>-1;},handle:function(evt){if(this.feature&&!this.feature.layer){this.feature=null;}
+var type=evt.type;var handled=false;var previouslyIn=!!(this.feature);var click=(type=="click"||type=="dblclick"||type=="touchstart");this.feature=this.layer.getFeatureFromEvent(evt);if(this.feature&&!this.feature.layer){this.feature=null;}
+if(this.lastFeature&&!this.lastFeature.layer){this.lastFeature=null;}
+if(this.feature){if(type==="touchstart"){OpenLayers.Event.stop(evt);}
+var inNew=(this.feature!=this.lastFeature);if(this.geometryTypeMatches(this.feature)){if(previouslyIn&&inNew){if(this.lastFeature){this.triggerCallback(type,'out',[this.lastFeature]);}
+this.triggerCallback(type,'in',[this.feature]);}else if(!previouslyIn||click){this.triggerCallback(type,'in',[this.feature]);}
+this.lastFeature=this.feature;handled=true;}else{if(this.lastFeature&&(previouslyIn&&inNew||click)){this.triggerCallback(type,'out',[this.lastFeature]);}
+this.feature=null;}}else{if(this.lastFeature&&(previouslyIn||click)){this.triggerCallback(type,'out',[this.lastFeature]);}}
+return handled;},triggerCallback:function(type,mode,args){var key=this.EVENTMAP[type][mode];if(key){if(type=='click'&&this.up&&this.down){var dpx=Math.sqrt(Math.pow(this.up.x-this.down.x,2)+
+Math.pow(this.up.y-this.down.y,2));if(dpx<=this.clickTolerance){this.callback(key,args);}}else{this.callback(key,args);}}},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.moveLayerToTop();this.map.events.on({"removelayer":this.handleMapEvents,"changelayer":this.handleMapEvents,scope:this});activated=true;}
+return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.moveLayerBack();this.feature=null;this.lastFeature=null;this.down=null;this.up=null;this.touch=false;this.map.events.un({"removelayer":this.handleMapEvents,"changelayer":this.handleMapEvents,scope:this});deactivated=true;}
+return deactivated;},handleMapEvents:function(evt){if(evt.type=="removelayer"||evt.property=="order"){this.moveLayerToTop();}},moveLayerToTop:function(){var index=Math.max(this.map.Z_INDEX_BASE['Feature']-1,this.layer.getZIndex())+1;this.layer.setZIndex(index);},moveLayerBack:function(){var index=this.layer.getZIndex()-1;if(index>=this.map.Z_INDEX_BASE['Feature']){this.layer.setZIndex(index);}else{this.map.setLayerZIndex(this.layer,this.map.getLayerIndex(this.layer));}},CLASS_NAME:"OpenLayers.Handler.Feature"});OpenLayers.StyleMap=OpenLayers.Class({styles:null,extendDefault:true,initialize:function(style,options){this.styles={"default":new OpenLayers.Style(OpenLayers.Feature.Vector.style["default"]),"select":new OpenLayers.Style(OpenLayers.Feature.Vector.style["select"]),"temporary":new OpenLayers.Style(OpenLayers.Feature.Vector.style["temporary"]),"delete":new OpenLayers.Style(OpenLayers.Feature.Vector.style["delete"])};if(style instanceof OpenLayers.Style){this.styles["default"]=style;this.styles["select"]=style;this.styles["temporary"]=style;this.styles["delete"]=style;}else if(typeof style=="object"){for(var key in style){if(style[key]instanceof OpenLayers.Style){this.styles[key]=style[key];}else if(typeof style[key]=="object"){this.styles[key]=new OpenLayers.Style(style[key]);}else{this.styles["default"]=new OpenLayers.Style(style);this.styles["select"]=new OpenLayers.Style(style);this.styles["temporary"]=new OpenLayers.Style(style);this.styles["delete"]=new OpenLayers.Style(style);break;}}}
+OpenLayers.Util.extend(this,options);},destroy:function(){for(var key in this.styles){this.styles[key].destroy();}
+this.styles=null;},createSymbolizer:function(feature,intent){if(!feature){feature=new OpenLayers.Feature.Vector();}
+if(!this.styles[intent]){intent="default";}
+feature.renderIntent=intent;var defaultSymbolizer={};if(this.extendDefault&&intent!="default"){defaultSymbolizer=this.styles["default"].createSymbolizer(feature);}
+return OpenLayers.Util.extend(defaultSymbolizer,this.styles[intent].createSymbolizer(feature));},addUniqueValueRules:function(renderIntent,property,symbolizers,context){var rules=[];for(var value in symbolizers){rules.push(new OpenLayers.Rule({symbolizer:symbolizers[value],context:context,filter:new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO,property:property,value:value})}));}
+this.styles[renderIntent].addRules(rules);},CLASS_NAME:"OpenLayers.StyleMap"});OpenLayers.Layer.Vector=OpenLayers.Class(OpenLayers.Layer,{isBaseLayer:false,isFixed:false,features:null,filter:null,selectedFeatures:null,unrenderedFeatures:null,reportError:true,style:null,styleMap:null,strategies:null,protocol:null,renderers:['SVG','VML','Canvas'],renderer:null,rendererOptions:null,geometryType:null,drawn:false,ratio:1,initialize:function(name,options){OpenLayers.Layer.prototype.initialize.apply(this,arguments);if(!this.renderer||!this.renderer.supported()){this.assignRenderer();}
+if(!this.renderer||!this.renderer.supported()){this.renderer=null;this.displayError();}
+if(!this.styleMap){this.styleMap=new OpenLayers.StyleMap();}
+this.features=[];this.selectedFeatures=[];this.unrenderedFeatures={};if(this.strategies){for(var i=0,len=this.strategies.length;i<len;i++){this.strategies[i].setLayer(this);}}},destroy:function(){if(this.strategies){var strategy,i,len;for(i=0,len=this.strategies.length;i<len;i++){strategy=this.strategies[i];if(strategy.autoDestroy){strategy.destroy();}}
+this.strategies=null;}
+if(this.protocol){if(this.protocol.autoDestroy){this.protocol.destroy();}
+this.protocol=null;}
+this.destroyFeatures();this.features=null;this.selectedFeatures=null;this.unrenderedFeatures=null;if(this.renderer){this.renderer.destroy();}
+this.renderer=null;this.geometryType=null;this.drawn=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Vector(this.name,this.getOptions());}
+obj=OpenLayers.Layer.prototype.clone.apply(this,[obj]);var features=this.features;var len=features.length;var clonedFeatures=new Array(len);for(var i=0;i<len;++i){clonedFeatures[i]=features[i].clone();}
+obj.features=clonedFeatures;return obj;},refresh:function(obj){if(this.calculateInRange()&&this.visibility){this.events.triggerEvent("refresh",obj);}},assignRenderer:function(){for(var i=0,len=this.renderers.length;i<len;i++){var rendererClass=this.renderers[i];var renderer=(typeof rendererClass=="function")?rendererClass:OpenLayers.Renderer[rendererClass];if(renderer&&renderer.prototype.supported()){this.renderer=new renderer(this.div,this.rendererOptions);break;}}},displayError:function(){if(this.reportError){OpenLayers.Console.userError(OpenLayers.i18n("browserNotSupported",{renderers:this.renderers.join('\n')}));}},setMap:function(map){OpenLayers.Layer.prototype.setMap.apply(this,arguments);if(!this.renderer){this.map.removeLayer(this);}else{this.renderer.map=this.map;var newSize=this.map.getSize();newSize.w=newSize.w*this.ratio;newSize.h=newSize.h*this.ratio;this.renderer.setSize(newSize);}},afterAdd:function(){if(this.strategies){var strategy,i,len;for(i=0,len=this.strategies.length;i<len;i++){strategy=this.strategies[i];if(strategy.autoActivate){strategy.activate();}}}},removeMap:function(map){this.drawn=false;if(this.strategies){var strategy,i,len;for(i=0,len=this.strategies.length;i<len;i++){strategy=this.strategies[i];if(strategy.autoActivate){strategy.deactivate();}}}},onMapResize:function(){OpenLayers.Layer.prototype.onMapResize.apply(this,arguments);var newSize=this.map.getSize();newSize.w=newSize.w*this.ratio;newSize.h=newSize.h*this.ratio;this.renderer.setSize(newSize);},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);var coordSysUnchanged=true;if(!dragging){this.renderer.root.style.visibility='hidden';var viewSize=this.map.getSize(),viewWidth=viewSize.w,viewHeight=viewSize.h,offsetLeft=(viewWidth/2*this.ratio)-viewWidth/2,offsetTop=(viewHeight/2*this.ratio)-viewHeight/2;offsetLeft+=parseInt(this.map.layerContainerDiv.style.left,10);offsetLeft=-Math.round(offsetLeft);offsetTop+=parseInt(this.map.layerContainerDiv.style.top,10);offsetTop=-Math.round(offsetTop);this.div.style.left=offsetLeft+'px';this.div.style.top=offsetTop+'px';var extent=this.map.getExtent().scale(this.ratio);coordSysUnchanged=this.renderer.setExtent(extent,zoomChanged);this.renderer.root.style.visibility='visible';if(OpenLayers.IS_GECKO===true){this.div.scrollLeft=this.div.scrollLeft;}
+if(!zoomChanged&&coordSysUnchanged){for(var i in this.unrenderedFeatures){var feature=this.unrenderedFeatures[i];this.drawFeature(feature);}}}
+if(!this.drawn||zoomChanged||!coordSysUnchanged){this.drawn=true;var feature;for(var i=0,len=this.features.length;i<len;i++){this.renderer.locked=(i!==(len-1));feature=this.features[i];this.drawFeature(feature);}}},display:function(display){OpenLayers.Layer.prototype.display.apply(this,arguments);var currentDisplay=this.div.style.display;if(currentDisplay!=this.renderer.root.style.display){this.renderer.root.style.display=currentDisplay;}},addFeatures:function(features,options){if(!(OpenLayers.Util.isArray(features))){features=[features];}
+var notify=!options||!options.silent;if(notify){var event={features:features};var ret=this.events.triggerEvent("beforefeaturesadded",event);if(ret===false){return;}
+features=event.features;}
+var featuresAdded=[];for(var i=0,len=features.length;i<len;i++){if(i!=(features.length-1)){this.renderer.locked=true;}else{this.renderer.locked=false;}
+var feature=features[i];if(this.geometryType&&!(feature.geometry instanceof this.geometryType)){throw new TypeError('addFeatures: component should be an '+
+this.geometryType.prototype.CLASS_NAME);}
+feature.layer=this;if(!feature.style&&this.style){feature.style=OpenLayers.Util.extend({},this.style);}
+if(notify){if(this.events.triggerEvent("beforefeatureadded",{feature:feature})===false){continue;}
+this.preFeatureInsert(feature);}
+featuresAdded.push(feature);this.features.push(feature);this.drawFeature(feature);if(notify){this.events.triggerEvent("featureadded",{feature:feature});this.onFeatureInsert(feature);}}
+if(notify){this.events.triggerEvent("featuresadded",{features:featuresAdded});}},removeFeatures:function(features,options){if(!features||features.length===0){return;}
+if(features===this.features){return this.removeAllFeatures(options);}
+if(!(OpenLayers.Util.isArray(features))){features=[features];}
+if(features===this.selectedFeatures){features=features.slice();}
+var notify=!options||!options.silent;if(notify){this.events.triggerEvent("beforefeaturesremoved",{features:features});}
+for(var i=features.length-1;i>=0;i--){if(i!=0&&features[i-1].geometry){this.renderer.locked=true;}else{this.renderer.locked=false;}
+var feature=features[i];delete this.unrenderedFeatures[feature.id];if(notify){this.events.triggerEvent("beforefeatureremoved",{feature:feature});}
+this.features=OpenLayers.Util.removeItem(this.features,feature);feature.layer=null;if(feature.geometry){this.renderer.eraseFeatures(feature);}
+if(OpenLayers.Util.indexOf(this.selectedFeatures,feature)!=-1){OpenLayers.Util.removeItem(this.selectedFeatures,feature);}
+if(notify){this.events.triggerEvent("featureremoved",{feature:feature});}}
+if(notify){this.events.triggerEvent("featuresremoved",{features:features});}},removeAllFeatures:function(options){var notify=!options||!options.silent;var features=this.features;if(notify){this.events.triggerEvent("beforefeaturesremoved",{features:features});}
+var feature;for(var i=features.length-1;i>=0;i--){feature=features[i];if(notify){this.events.triggerEvent("beforefeatureremoved",{feature:feature});}
+feature.layer=null;if(notify){this.events.triggerEvent("featureremoved",{feature:feature});}}
+this.renderer.clear();this.features=[];this.unrenderedFeatures={};this.selectedFeatures=[];if(notify){this.events.triggerEvent("featuresremoved",{features:features});}},destroyFeatures:function(features,options){var all=(features==undefined);if(all){features=this.features;}
+if(features){this.removeFeatures(features,options);for(var i=features.length-1;i>=0;i--){features[i].destroy();}}},drawFeature:function(feature,style){if(!this.drawn){return;}
+if(typeof style!="object"){if(!style&&feature.state===OpenLayers.State.DELETE){style="delete";}
+var renderIntent=style||feature.renderIntent;style=feature.style||this.style;if(!style){style=this.styleMap.createSymbolizer(feature,renderIntent);}}
+var drawn=this.renderer.drawFeature(feature,style);if(drawn===false||drawn===null){this.unrenderedFeatures[feature.id]=feature;}else{delete this.unrenderedFeatures[feature.id];}},eraseFeatures:function(features){this.renderer.eraseFeatures(features);},getFeatureFromEvent:function(evt){if(!this.renderer){throw new Error('getFeatureFromEvent called on layer with no '+'renderer. This usually means you destroyed a '+'layer, but not some handler which is associated '+'with it.');}
+var feature=null;var featureId=this.renderer.getFeatureIdFromEvent(evt);if(featureId){if(typeof featureId==="string"){feature=this.getFeatureById(featureId);}else{feature=featureId;}}
+return feature;},getFeatureBy:function(property,value){var feature=null;for(var i=0,len=this.features.length;i<len;++i){if(this.features[i][property]==value){feature=this.features[i];break;}}
+return feature;},getFeatureById:function(featureId){return this.getFeatureBy('id',featureId);},getFeatureByFid:function(featureFid){return this.getFeatureBy('fid',featureFid);},getFeaturesByAttribute:function(attrName,attrValue){var i,feature,len=this.features.length,foundFeatures=[];for(i=0;i<len;i++){feature=this.features[i];if(feature&&feature.attributes){if(feature.attributes[attrName]===attrValue){foundFeatures.push(feature);}}}
+return foundFeatures;},onFeatureInsert:function(feature){},preFeatureInsert:function(feature){},getDataExtent:function(){var maxExtent=null;var features=this.features;if(features&&(features.length>0)){var geometry=null;for(var i=0,len=features.length;i<len;i++){geometry=features[i].geometry;if(geometry){if(maxExtent===null){maxExtent=new OpenLayers.Bounds();}
+maxExtent.extend(geometry.getBounds());}}}
+return maxExtent;},CLASS_NAME:"OpenLayers.Layer.Vector"});OpenLayers.Layer.Vector.RootContainer=OpenLayers.Class(OpenLayers.Layer.Vector,{displayInLayerSwitcher:false,layers:null,display:function(){},getFeatureFromEvent:function(evt){var layers=this.layers;var feature;for(var i=0;i<layers.length;i++){feature=layers[i].getFeatureFromEvent(evt);if(feature){return feature;}}},setMap:function(map){OpenLayers.Layer.Vector.prototype.setMap.apply(this,arguments);this.collectRoots();map.events.register("changelayer",this,this.handleChangeLayer);},removeMap:function(map){map.events.unregister("changelayer",this,this.handleChangeLayer);this.resetRoots();OpenLayers.Layer.Vector.prototype.removeMap.apply(this,arguments);},collectRoots:function(){var layer;for(var i=0;i<this.map.layers.length;++i){layer=this.map.layers[i];if(OpenLayers.Util.indexOf(this.layers,layer)!=-1){layer.renderer.moveRoot(this.renderer);}}},resetRoots:function(){var layer;for(var i=0;i<this.layers.length;++i){layer=this.layers[i];if(this.renderer&&layer.renderer.getRenderLayerId()==this.id){this.renderer.moveRoot(layer.renderer);}}},handleChangeLayer:function(evt){var layer=evt.layer;if(evt.property=="order"&&OpenLayers.Util.indexOf(this.layers,layer)!=-1){this.resetRoots();this.collectRoots();}},CLASS_NAME:"OpenLayers.Layer.Vector.RootContainer"});OpenLayers.Control.SelectFeature=OpenLayers.Class(OpenLayers.Control,{multipleKey:null,toggleKey:null,multiple:false,clickout:true,toggle:false,hover:false,highlightOnly:false,box:false,onBeforeSelect:function(){},onSelect:function(){},onUnselect:function(){},scope:null,geometryTypes:null,layer:null,layers:null,callbacks:null,selectStyle:null,renderIntent:"select",handlers:null,initialize:function(layers,options){OpenLayers.Control.prototype.initialize.apply(this,[options]);if(this.scope===null){this.scope=this;}
+this.initLayer(layers);var callbacks={click:this.clickFeature,clickout:this.clickoutFeature};if(this.hover){callbacks.over=this.overFeature;callbacks.out=this.outFeature;}
+this.callbacks=OpenLayers.Util.extend(callbacks,this.callbacks);this.handlers={feature:new OpenLayers.Handler.Feature(this,this.layer,this.callbacks,{geometryTypes:this.geometryTypes})};if(this.box){this.handlers.box=new OpenLayers.Handler.Box(this,{done:this.selectBox},{boxDivClassName:"olHandlerBoxSelectFeature"});}},initLayer:function(layers){if(OpenLayers.Util.isArray(layers)){this.layers=layers;this.layer=new OpenLayers.Layer.Vector.RootContainer(this.id+"_container",{layers:layers});}else{this.layer=layers;}},destroy:function(){if(this.active&&this.layers){this.map.removeLayer(this.layer);}
+OpenLayers.Control.prototype.destroy.apply(this,arguments);if(this.layers){this.layer.destroy();}},activate:function(){if(!this.active){if(this.layers){this.map.addLayer(this.layer);}
+this.handlers.feature.activate();if(this.box&&this.handlers.box){this.handlers.box.activate();}}
+return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){if(this.active){this.handlers.feature.deactivate();if(this.handlers.box){this.handlers.box.deactivate();}
+if(this.layers){this.map.removeLayer(this.layer);}}
+return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},unselectAll:function(options){var layers=this.layers||[this.layer];var layer,feature;for(var l=0;l<layers.length;++l){layer=layers[l];for(var i=layer.selectedFeatures.length-1;i>=0;--i){feature=layer.selectedFeatures[i];if(!options||options.except!=feature){this.unselect(feature);}}}},clickFeature:function(feature){if(!this.hover){var selected=(OpenLayers.Util.indexOf(feature.layer.selectedFeatures,feature)>-1);if(selected){if(this.toggleSelect()){this.unselect(feature);}else if(!this.multipleSelect()){this.unselectAll({except:feature});}}else{if(!this.multipleSelect()){this.unselectAll({except:feature});}
+this.select(feature);}}},multipleSelect:function(){return this.multiple||(this.handlers.feature.evt&&this.handlers.feature.evt[this.multipleKey]);},toggleSelect:function(){return this.toggle||(this.handlers.feature.evt&&this.handlers.feature.evt[this.toggleKey]);},clickoutFeature:function(feature){if(!this.hover&&this.clickout){this.unselectAll();}},overFeature:function(feature){var layer=feature.layer;if(this.hover){if(this.highlightOnly){this.highlight(feature);}else if(OpenLayers.Util.indexOf(layer.selectedFeatures,feature)==-1){this.select(feature);}}},outFeature:function(feature){if(this.hover){if(this.highlightOnly){if(feature._lastHighlighter==this.id){if(feature._prevHighlighter&&feature._prevHighlighter!=this.id){delete feature._lastHighlighter;var control=this.map.getControl(feature._prevHighlighter);if(control){control.highlight(feature);}}else{this.unhighlight(feature);}}}else{this.unselect(feature);}}},highlight:function(feature){var layer=feature.layer;var cont=this.events.triggerEvent("beforefeaturehighlighted",{feature:feature});if(cont!==false){feature._prevHighlighter=feature._lastHighlighter;feature._lastHighlighter=this.id;var style=this.selectStyle||this.renderIntent;layer.drawFeature(feature,style);this.events.triggerEvent("featurehighlighted",{feature:feature});}},unhighlight:function(feature){var layer=feature.layer;if(feature._prevHighlighter==undefined){delete feature._lastHighlighter;}else if(feature._prevHighlighter==this.id){delete feature._prevHighlighter;}else{feature._lastHighlighter=feature._prevHighlighter;delete feature._prevHighlighter;}
+layer.drawFeature(feature,feature.style||feature.layer.style||"default");this.events.triggerEvent("featureunhighlighted",{feature:feature});},select:function(feature){var cont=this.onBeforeSelect.call(this.scope,feature);var layer=feature.layer;if(cont!==false){cont=layer.events.triggerEvent("beforefeatureselected",{feature:feature});if(cont!==false){layer.selectedFeatures.push(feature);this.highlight(feature);if(!this.handlers.feature.lastFeature){this.handlers.feature.lastFeature=layer.selectedFeatures[0];}
+layer.events.triggerEvent("featureselected",{feature:feature});this.onSelect.call(this.scope,feature);}}},unselect:function(feature){var layer=feature.layer;this.unhighlight(feature);OpenLayers.Util.removeItem(layer.selectedFeatures,feature);layer.events.triggerEvent("featureunselected",{feature:feature});this.onUnselect.call(this.scope,feature);},selectBox:function(position){if(position instanceof OpenLayers.Bounds){var minXY=this.map.getLonLatFromPixel({x:position.left,y:position.bottom});var maxXY=this.map.getLonLatFromPixel({x:position.right,y:position.top});var bounds=new OpenLayers.Bounds(minXY.lon,minXY.lat,maxXY.lon,maxXY.lat);if(!this.multipleSelect()){this.unselectAll();}
+var prevMultiple=this.multiple;this.multiple=true;var layers=this.layers||[this.layer];this.events.triggerEvent("boxselectionstart",{layers:layers});var layer;for(var l=0;l<layers.length;++l){layer=layers[l];for(var i=0,len=layer.features.length;i<len;++i){var feature=layer.features[i];if(!feature.getVisibility()){continue;}
+if(this.geometryTypes==null||OpenLayers.Util.indexOf(this.geometryTypes,feature.geometry.CLASS_NAME)>-1){if(bounds.toGeometry().intersects(feature.geometry)){if(OpenLayers.Util.indexOf(layer.selectedFeatures,feature)==-1){this.select(feature);}}}}}
+this.multiple=prevMultiple;this.events.triggerEvent("boxselectionend",{layers:layers});}},setMap:function(map){this.handlers.feature.setMap(map);if(this.box){this.handlers.box.setMap(map);}
+OpenLayers.Control.prototype.setMap.apply(this,arguments);},setLayer:function(layers){var isActive=this.active;this.unselectAll();this.deactivate();if(this.layers){this.layer.destroy();this.layers=null;}
+this.initLayer(layers);this.handlers.feature.layer=this.layer;if(isActive){this.activate();}},CLASS_NAME:"OpenLayers.Control.SelectFeature"});OpenLayers.Control.Attribution=OpenLayers.Class(OpenLayers.Control,{separator:", ",template:"${layers}",destroy:function(){this.map.events.un({"removelayer":this.updateAttribution,"addlayer":this.updateAttribution,"changelayer":this.updateAttribution,"changebaselayer":this.updateAttribution,scope:this});OpenLayers.Control.prototype.destroy.apply(this,arguments);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.map.events.on({'changebaselayer':this.updateAttribution,'changelayer':this.updateAttribution,'addlayer':this.updateAttribution,'removelayer':this.updateAttribution,scope:this});this.updateAttribution();return this.div;},updateAttribution:function(){var attributions=[];if(this.map&&this.map.layers){for(var i=0,len=this.map.layers.length;i<len;i++){var layer=this.map.layers[i];if(layer.attribution&&layer.getVisibility()){if(OpenLayers.Util.indexOf(attributions,layer.attribution)===-1){attributions.push(layer.attribution);}}}
+this.div.innerHTML=OpenLayers.String.format(this.template,{layers:attributions.join(this.separator)});}},CLASS_NAME:"OpenLayers.Control.Attribution"});OpenLayers.Handler.Point=OpenLayers.Class(OpenLayers.Handler,{point:null,layer:null,multi:false,citeCompliant:false,mouseDown:false,stoppedDown:null,lastDown:null,lastUp:null,persist:false,stopDown:false,stopUp:false,layerOptions:null,pixelTolerance:5,touch:false,lastTouchPx:null,initialize:function(control,callbacks,options){if(!(options&&options.layerOptions&&options.layerOptions.styleMap)){this.style=OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'],{});}
+OpenLayers.Handler.prototype.initialize.apply(this,arguments);},activate:function(){if(!OpenLayers.Handler.prototype.activate.apply(this,arguments)){return false;}
+var options=OpenLayers.Util.extend({displayInLayerSwitcher:false,calculateInRange:OpenLayers.Function.True,wrapDateLine:this.citeCompliant},this.layerOptions);this.layer=new OpenLayers.Layer.Vector(this.CLASS_NAME,options);this.map.addLayer(this.layer);return true;},createFeature:function(pixel){var lonlat=this.layer.getLonLatFromViewPortPx(pixel);var geometry=new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat);this.point=new OpenLayers.Feature.Vector(geometry);this.callback("create",[this.point.geometry,this.point]);this.point.geometry.clearBounds();this.layer.addFeatures([this.point],{silent:true});},deactivate:function(){if(!OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){return false;}
+this.cancel();if(this.layer.map!=null){this.destroyFeature(true);this.layer.destroy(false);}
+this.layer=null;this.touch=false;return true;},destroyFeature:function(force){if(this.layer&&(force||!this.persist)){this.layer.destroyFeatures();}
+this.point=null;},destroyPersistedFeature:function(){var layer=this.layer;if(layer&&layer.features.length>1){this.layer.features[0].destroy();}},finalize:function(cancel){var key=cancel?"cancel":"done";this.mouseDown=false;this.lastDown=null;this.lastUp=null;this.lastTouchPx=null;this.callback(key,[this.geometryClone()]);this.destroyFeature(cancel);},cancel:function(){this.finalize(true);},click:function(evt){OpenLayers.Event.stop(evt);return false;},dblclick:function(evt){OpenLayers.Event.stop(evt);return false;},modifyFeature:function(pixel){if(!this.point){this.createFeature(pixel);}
+var lonlat=this.layer.getLonLatFromViewPortPx(pixel);this.point.geometry.x=lonlat.lon;this.point.geometry.y=lonlat.lat;this.callback("modify",[this.point.geometry,this.point,false]);this.point.geometry.clearBounds();this.drawFeature();},drawFeature:function(){this.layer.drawFeature(this.point,this.style);},getGeometry:function(){var geometry=this.point&&this.point.geometry;if(geometry&&this.multi){geometry=new OpenLayers.Geometry.MultiPoint([geometry]);}
+return geometry;},geometryClone:function(){var geom=this.getGeometry();return geom&&geom.clone();},mousedown:function(evt){return this.down(evt);},touchstart:function(evt){if(!this.touch){this.touch=true;this.map.events.un({mousedown:this.mousedown,mouseup:this.mouseup,mousemove:this.mousemove,click:this.click,dblclick:this.dblclick,scope:this});}
+this.lastTouchPx=evt.xy;return this.down(evt);},mousemove:function(evt){return this.move(evt);},touchmove:function(evt){this.lastTouchPx=evt.xy;return this.move(evt);},mouseup:function(evt){return this.up(evt);},touchend:function(evt){evt.xy=this.lastTouchPx;return this.up(evt);},down:function(evt){this.mouseDown=true;this.lastDown=evt.xy;if(!this.touch){this.modifyFeature(evt.xy);}
+this.stoppedDown=this.stopDown;return!this.stopDown;},move:function(evt){if(!this.touch&&(!this.mouseDown||this.stoppedDown)){this.modifyFeature(evt.xy);}
+return true;},up:function(evt){this.mouseDown=false;this.stoppedDown=this.stopDown;if(!this.checkModifiers(evt)){return true;}
+if(this.lastUp&&this.lastUp.equals(evt.xy)){return true;}
+if(this.lastDown&&this.passesTolerance(this.lastDown,evt.xy,this.pixelTolerance)){if(this.touch){this.modifyFeature(evt.xy);}
+if(this.persist){this.destroyPersistedFeature();}
+this.lastUp=evt.xy;this.finalize();return!this.stopUp;}else{return true;}},mouseout:function(evt){if(OpenLayers.Util.mouseLeft(evt,this.map.viewPortDiv)){this.stoppedDown=this.stopDown;this.mouseDown=false;}},passesTolerance:function(pixel1,pixel2,tolerance){var passes=true;if(tolerance!=null&&pixel1&&pixel2){var dist=pixel1.distanceTo(pixel2);if(dist>tolerance){passes=false;}}
+return passes;},CLASS_NAME:"OpenLayers.Handler.Point"});OpenLayers.Handler.Drag=OpenLayers.Class(OpenLayers.Handler,{started:false,stopDown:true,dragging:false,touch:false,last:null,start:null,lastMoveEvt:null,oldOnselectstart:null,interval:0,timeoutId:null,documentDrag:false,documentEvents:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);if(this.documentDrag===true){var me=this;this._docMove=function(evt){me.mousemove({xy:{x:evt.clientX,y:evt.clientY},element:document});};this._docUp=function(evt){me.mouseup({xy:{x:evt.clientX,y:evt.clientY}});};}},dragstart:function(evt){var propagate=true;this.dragging=false;if(this.checkModifiers(evt)&&(OpenLayers.Event.isLeftClick(evt)||OpenLayers.Event.isSingleTouch(evt))){this.started=true;this.start=evt.xy;this.last=evt.xy;OpenLayers.Element.addClass(this.map.viewPortDiv,"olDragDown");this.down(evt);this.callback("down",[evt.xy]);OpenLayers.Event.stop(evt);if(!this.oldOnselectstart){this.oldOnselectstart=document.onselectstart?document.onselectstart:OpenLayers.Function.True;}
+document.onselectstart=OpenLayers.Function.False;propagate=!this.stopDown;}else{this.started=false;this.start=null;this.last=null;}
+return propagate;},dragmove:function(evt){this.lastMoveEvt=evt;if(this.started&&!this.timeoutId&&(evt.xy.x!=this.last.x||evt.xy.y!=this.last.y)){if(this.documentDrag===true&&this.documentEvents){if(evt.element===document){this.adjustXY(evt);this.setEvent(evt);}else{this.removeDocumentEvents();}}
+if(this.interval>0){this.timeoutId=setTimeout(OpenLayers.Function.bind(this.removeTimeout,this),this.interval);}
+this.dragging=true;this.move(evt);this.callback("move",[evt.xy]);if(!this.oldOnselectstart){this.oldOnselectstart=document.onselectstart;document.onselectstart=OpenLayers.Function.False;}
+this.last=evt.xy;}
+return true;},dragend:function(evt){if(this.started){if(this.documentDrag===true&&this.documentEvents){this.adjustXY(evt);this.removeDocumentEvents();}
+var dragged=(this.start!=this.last);this.started=false;this.dragging=false;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");this.up(evt);this.callback("up",[evt.xy]);if(dragged){this.callback("done",[evt.xy]);}
+document.onselectstart=this.oldOnselectstart;}
+return true;},down:function(evt){},move:function(evt){},up:function(evt){},out:function(evt){},mousedown:function(evt){return this.dragstart(evt);},touchstart:function(evt){if(!this.touch){this.touch=true;this.map.events.un({mousedown:this.mousedown,mouseup:this.mouseup,mousemove:this.mousemove,click:this.click,scope:this});}
+return this.dragstart(evt);},mousemove:function(evt){return this.dragmove(evt);},touchmove:function(evt){return this.dragmove(evt);},removeTimeout:function(){this.timeoutId=null;if(this.dragging){this.mousemove(this.lastMoveEvt);}},mouseup:function(evt){return this.dragend(evt);},touchend:function(evt){evt.xy=this.last;return this.dragend(evt);},mouseout:function(evt){if(this.started&&OpenLayers.Util.mouseLeft(evt,this.map.viewPortDiv)){if(this.documentDrag===true){this.addDocumentEvents();}else{var dragged=(this.start!=this.last);this.started=false;this.dragging=false;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");this.out(evt);this.callback("out",[]);if(dragged){this.callback("done",[evt.xy]);}
+if(document.onselectstart){document.onselectstart=this.oldOnselectstart;}}}
+return true;},click:function(evt){return(this.start==this.last);},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.dragging=false;activated=true;}
+return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.touch=false;this.started=false;this.dragging=false;this.start=null;this.last=null;deactivated=true;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");}
+return deactivated;},adjustXY:function(evt){var pos=OpenLayers.Util.pagePosition(this.map.viewPortDiv);evt.xy.x-=pos[0];evt.xy.y-=pos[1];},addDocumentEvents:function(){OpenLayers.Element.addClass(document.body,"olDragDown");this.documentEvents=true;OpenLayers.Event.observe(document,"mousemove",this._docMove);OpenLayers.Event.observe(document,"mouseup",this._docUp);},removeDocumentEvents:function(){OpenLayers.Element.removeClass(document.body,"olDragDown");this.documentEvents=false;OpenLayers.Event.stopObserving(document,"mousemove",this._docMove);OpenLayers.Event.stopObserving(document,"mouseup",this._docUp);},CLASS_NAME:"OpenLayers.Handler.Drag"});OpenLayers.Control.DragFeature=OpenLayers.Class(OpenLayers.Control,{geometryTypes:null,onStart:function(feature,pixel){},onDrag:function(feature,pixel){},onComplete:function(feature,pixel){},onEnter:function(feature){},onLeave:function(feature){},documentDrag:false,layer:null,feature:null,dragCallbacks:{},featureCallbacks:{},lastPixel:null,initialize:function(layer,options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.layer=layer;this.handlers={drag:new OpenLayers.Handler.Drag(this,OpenLayers.Util.extend({down:this.downFeature,move:this.moveFeature,up:this.upFeature,out:this.cancel,done:this.doneDragging},this.dragCallbacks),{documentDrag:this.documentDrag}),feature:new OpenLayers.Handler.Feature(this,this.layer,OpenLayers.Util.extend({click:this.clickFeature,clickout:this.clickoutFeature,over:this.overFeature,out:this.outFeature},this.featureCallbacks),{geometryTypes:this.geometryTypes})};},clickFeature:function(feature){if(this.handlers.feature.touch&&!this.over&&this.overFeature(feature)){this.handlers.drag.dragstart(this.handlers.feature.evt);this.handlers.drag.stopDown=false;}},clickoutFeature:function(feature){if(this.handlers.feature.touch&&this.over){this.outFeature(feature);this.handlers.drag.stopDown=true;}},destroy:function(){this.layer=null;OpenLayers.Control.prototype.destroy.apply(this,[]);},activate:function(){return(this.handlers.feature.activate()&&OpenLayers.Control.prototype.activate.apply(this,arguments));},deactivate:function(){this.handlers.drag.deactivate();this.handlers.feature.deactivate();this.feature=null;this.dragging=false;this.lastPixel=null;OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass+"Over");return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},overFeature:function(feature){var activated=false;if(!this.handlers.drag.dragging){this.feature=feature;this.handlers.drag.activate();activated=true;this.over=true;OpenLayers.Element.addClass(this.map.viewPortDiv,this.displayClass+"Over");this.onEnter(feature);}else{if(this.feature.id==feature.id){this.over=true;}else{this.over=false;}}
+return activated;},downFeature:function(pixel){this.lastPixel=pixel;this.onStart(this.feature,pixel);},moveFeature:function(pixel){var res=this.map.getResolution();this.feature.geometry.move(res*(pixel.x-this.lastPixel.x),res*(this.lastPixel.y-pixel.y));this.layer.drawFeature(this.feature);this.lastPixel=pixel;this.onDrag(this.feature,pixel);},upFeature:function(pixel){if(!this.over){this.handlers.drag.deactivate();}},doneDragging:function(pixel){this.onComplete(this.feature,pixel);},outFeature:function(feature){if(!this.handlers.drag.dragging){this.over=false;this.handlers.drag.deactivate();OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass+"Over");this.onLeave(feature);this.feature=null;}else{if(this.feature.id==feature.id){this.over=false;}}},cancel:function(){this.handlers.drag.deactivate();this.over=false;},setMap:function(map){this.handlers.drag.setMap(map);this.handlers.feature.setMap(map);OpenLayers.Control.prototype.setMap.apply(this,arguments);},CLASS_NAME:"OpenLayers.Control.DragFeature"});OpenLayers.Control.TransformFeature=OpenLayers.Class(OpenLayers.Control,{geometryTypes:null,layer:null,preserveAspectRatio:false,rotate:true,feature:null,renderIntent:"temporary",rotationHandleSymbolizer:null,box:null,center:null,scale:1,ratio:1,rotation:0,handles:null,rotationHandles:null,dragControl:null,irregular:false,initialize:function(layer,options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.layer=layer;if(!this.rotationHandleSymbolizer){this.rotationHandleSymbolizer={stroke:false,pointRadius:10,fillOpacity:0,cursor:"pointer"};}
+this.createBox();this.createControl();},activate:function(){var activated=false;if(OpenLayers.Control.prototype.activate.apply(this,arguments)){this.dragControl.activate();this.layer.addFeatures([this.box]);this.rotate&&this.layer.addFeatures(this.rotationHandles);this.layer.addFeatures(this.handles);activated=true;}
+return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){this.layer.removeFeatures(this.handles);this.rotate&&this.layer.removeFeatures(this.rotationHandles);this.layer.removeFeatures([this.box]);this.dragControl.deactivate();deactivated=true;}
+return deactivated;},setMap:function(map){this.dragControl.setMap(map);OpenLayers.Control.prototype.setMap.apply(this,arguments);},setFeature:function(feature,initialParams){initialParams=OpenLayers.Util.applyDefaults(initialParams,{rotation:0,scale:1,ratio:1});var oldRotation=this.rotation;var oldCenter=this.center;OpenLayers.Util.extend(this,initialParams);var cont=this.events.triggerEvent("beforesetfeature",{feature:feature});if(cont===false){return;}
+this.feature=feature;this.activate();this._setfeature=true;var featureBounds=this.feature.geometry.getBounds();this.box.move(featureBounds.getCenterLonLat());this.box.geometry.rotate(-oldRotation,oldCenter);this._angle=0;var ll;if(this.rotation){var geom=feature.geometry.clone();geom.rotate(-this.rotation,this.center);var box=new OpenLayers.Feature.Vector(geom.getBounds().toGeometry());box.geometry.rotate(this.rotation,this.center);this.box.geometry.rotate(this.rotation,this.center);this.box.move(box.geometry.getBounds().getCenterLonLat());var llGeom=box.geometry.components[0].components[0];ll=llGeom.getBounds().getCenterLonLat();}else{ll=new OpenLayers.LonLat(featureBounds.left,featureBounds.bottom);}
+this.handles[0].move(ll);delete this._setfeature;this.events.triggerEvent("setfeature",{feature:feature});},unsetFeature:function(){if(this.active){this.deactivate();}else{this.feature=null;this.rotation=0;this.scale=1;this.ratio=1;}},createBox:function(){var control=this;this.center=new OpenLayers.Geometry.Point(0,0);this.box=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString([new OpenLayers.Geometry.Point(-1,-1),new OpenLayers.Geometry.Point(0,-1),new OpenLayers.Geometry.Point(1,-1),new OpenLayers.Geometry.Point(1,0),new OpenLayers.Geometry.Point(1,1),new OpenLayers.Geometry.Point(0,1),new OpenLayers.Geometry.Point(-1,1),new OpenLayers.Geometry.Point(-1,0),new OpenLayers.Geometry.Point(-1,-1)]),null,typeof this.renderIntent=="string"?null:this.renderIntent);this.box.geometry.move=function(x,y){control._moving=true;OpenLayers.Geometry.LineString.prototype.move.apply(this,arguments);control.center.move(x,y);delete control._moving;};var vertexMoveFn=function(x,y){OpenLayers.Geometry.Point.prototype.move.apply(this,arguments);this._rotationHandle&&this._rotationHandle.geometry.move(x,y);this._handle.geometry.move(x,y);};var vertexResizeFn=function(scale,center,ratio){OpenLayers.Geometry.Point.prototype.resize.apply(this,arguments);this._rotationHandle&&this._rotationHandle.geometry.resize(scale,center,ratio);this._handle.geometry.resize(scale,center,ratio);};var vertexRotateFn=function(angle,center){OpenLayers.Geometry.Point.prototype.rotate.apply(this,arguments);this._rotationHandle&&this._rotationHandle.geometry.rotate(angle,center);this._handle.geometry.rotate(angle,center);};var handleMoveFn=function(x,y){var oldX=this.x,oldY=this.y;OpenLayers.Geometry.Point.prototype.move.call(this,x,y);if(control._moving){return;}
+var evt=control.dragControl.handlers.drag.evt;var preserveAspectRatio=!control._setfeature&&control.preserveAspectRatio;var reshape=!preserveAspectRatio&&!(evt&&evt.shiftKey);var oldGeom=new OpenLayers.Geometry.Point(oldX,oldY);var centerGeometry=control.center;this.rotate(-control.rotation,centerGeometry);oldGeom.rotate(-control.rotation,centerGeometry);var dx1=this.x-centerGeometry.x;var dy1=this.y-centerGeometry.y;var dx0=dx1-(this.x-oldGeom.x);var dy0=dy1-(this.y-oldGeom.y);if(control.irregular&&!control._setfeature){dx1-=(this.x-oldGeom.x)/2;dy1-=(this.y-oldGeom.y)/2;}
+this.x=oldX;this.y=oldY;var scale,ratio=1;if(reshape){scale=Math.abs(dy0)<0.00001?1:dy1/dy0;ratio=(Math.abs(dx0)<0.00001?1:(dx1/dx0))/scale;}else{var l0=Math.sqrt((dx0*dx0)+(dy0*dy0));var l1=Math.sqrt((dx1*dx1)+(dy1*dy1));scale=l1/l0;}
+control._moving=true;control.box.geometry.rotate(-control.rotation,centerGeometry);delete control._moving;control.box.geometry.resize(scale,centerGeometry,ratio);control.box.geometry.rotate(control.rotation,centerGeometry);control.transformFeature({scale:scale,ratio:ratio});if(control.irregular&&!control._setfeature){var newCenter=centerGeometry.clone();newCenter.x+=Math.abs(oldX-centerGeometry.x)<0.00001?0:(this.x-oldX);newCenter.y+=Math.abs(oldY-centerGeometry.y)<0.00001?0:(this.y-oldY);control.box.geometry.move(this.x-oldX,this.y-oldY);control.transformFeature({center:newCenter});}};var rotationHandleMoveFn=function(x,y){var oldX=this.x,oldY=this.y;OpenLayers.Geometry.Point.prototype.move.call(this,x,y);if(control._moving){return;}
+var evt=control.dragControl.handlers.drag.evt;var constrain=(evt&&evt.shiftKey)?45:1;var centerGeometry=control.center;var dx1=this.x-centerGeometry.x;var dy1=this.y-centerGeometry.y;var dx0=dx1-x;var dy0=dy1-y;this.x=oldX;this.y=oldY;var a0=Math.atan2(dy0,dx0);var a1=Math.atan2(dy1,dx1);var angle=a1-a0;angle*=180/Math.PI;control._angle=(control._angle+angle)%360;var diff=control.rotation%constrain;if(Math.abs(control._angle)>=constrain||diff!==0){angle=Math.round(control._angle/constrain)*constrain-
+diff;control._angle=0;control.box.geometry.rotate(angle,centerGeometry);control.transformFeature({rotation:angle});}};var handles=new Array(8);var rotationHandles=new Array(4);var geom,handle,rotationHandle;var positions=["sw","s","se","e","ne","n","nw","w"];for(var i=0;i<8;++i){geom=this.box.geometry.components[i];handle=new OpenLayers.Feature.Vector(geom.clone(),{role:positions[i]+"-resize"},typeof this.renderIntent=="string"?null:this.renderIntent);if(i%2==0){rotationHandle=new OpenLayers.Feature.Vector(geom.clone(),{role:positions[i]+"-rotate"},typeof this.rotationHandleSymbolizer=="string"?null:this.rotationHandleSymbolizer);rotationHandle.geometry.move=rotationHandleMoveFn;geom._rotationHandle=rotationHandle;rotationHandles[i/2]=rotationHandle;}
+geom.move=vertexMoveFn;geom.resize=vertexResizeFn;geom.rotate=vertexRotateFn;handle.geometry.move=handleMoveFn;geom._handle=handle;handles[i]=handle;}
+this.rotationHandles=rotationHandles;this.handles=handles;},createControl:function(){var control=this;this.dragControl=new OpenLayers.Control.DragFeature(this.layer,{documentDrag:true,moveFeature:function(pixel){if(this.feature===control.feature){this.feature=control.box;}
+OpenLayers.Control.DragFeature.prototype.moveFeature.apply(this,arguments);},onDrag:function(feature,pixel){if(feature===control.box){control.transformFeature({center:control.center});}},onStart:function(feature,pixel){var eligible=!control.geometryTypes||OpenLayers.Util.indexOf(control.geometryTypes,feature.geometry.CLASS_NAME)!==-1;var i=OpenLayers.Util.indexOf(control.handles,feature);i+=OpenLayers.Util.indexOf(control.rotationHandles,feature);if(feature!==control.feature&&feature!==control.box&&i==-2&&eligible){control.setFeature(feature);}},onComplete:function(feature,pixel){control.events.triggerEvent("transformcomplete",{feature:control.feature});}});},drawHandles:function(){var layer=this.layer;for(var i=0;i<8;++i){if(this.rotate&&i%2===0){layer.drawFeature(this.rotationHandles[i/2],this.rotationHandleSymbolizer);}
+layer.drawFeature(this.handles[i],this.renderIntent);}},transformFeature:function(mods){if(!this._setfeature){this.scale*=(mods.scale||1);this.ratio*=(mods.ratio||1);var oldRotation=this.rotation;this.rotation=(this.rotation+(mods.rotation||0))%360;if(this.events.triggerEvent("beforetransform",mods)!==false){var feature=this.feature;var geom=feature.geometry;var center=this.center;geom.rotate(-oldRotation,center);if(mods.scale||mods.ratio){geom.resize(mods.scale,center,mods.ratio);}else if(mods.center){feature.move(mods.center.getBounds().getCenterLonLat());}
+geom.rotate(this.rotation,center);this.layer.drawFeature(feature);feature.toState(OpenLayers.State.UPDATE);this.events.triggerEvent("transform",mods);}}
+this.layer.drawFeature(this.box,this.renderIntent);this.drawHandles();},destroy:function(){var geom;for(var i=0;i<8;++i){geom=this.box.geometry.components[i];geom._handle.destroy();geom._handle=null;geom._rotationHandle&&geom._rotationHandle.destroy();geom._rotationHandle=null;}
+this.center=null;this.feature=null;this.handles=null;this.rotationHandleSymbolizer=null;this.rotationHandles=null;this.box.destroy();this.box=null;this.layer=null;this.dragControl.destroy();this.dragControl=null;OpenLayers.Control.prototype.destroy.apply(this,arguments);},CLASS_NAME:"OpenLayers.Control.TransformFeature"});OpenLayers.Filter.Logical=OpenLayers.Class(OpenLayers.Filter,{filters:null,type:null,initialize:function(options){this.filters=[];OpenLayers.Filter.prototype.initialize.apply(this,[options]);},destroy:function(){this.filters=null;OpenLayers.Filter.prototype.destroy.apply(this);},evaluate:function(context){var i,len;switch(this.type){case OpenLayers.Filter.Logical.AND:for(i=0,len=this.filters.length;i<len;i++){if(this.filters[i].evaluate(context)==false){return false;}}
+return true;case OpenLayers.Filter.Logical.OR:for(i=0,len=this.filters.length;i<len;i++){if(this.filters[i].evaluate(context)==true){return true;}}
+return false;case OpenLayers.Filter.Logical.NOT:return(!this.filters[0].evaluate(context));}
+return undefined;},clone:function(){var filters=[];for(var i=0,len=this.filters.length;i<len;++i){filters.push(this.filters[i].clone());}
+return new OpenLayers.Filter.Logical({type:this.type,filters:filters});},CLASS_NAME:"OpenLayers.Filter.Logical"});OpenLayers.Filter.Logical.AND="&&";OpenLayers.Filter.Logical.OR="||";OpenLayers.Filter.Logical.NOT="!";OpenLayers.Lang["ia"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Le responsa a un requesta non esseva maneate: ${statusText}",'Permalink':"Permaligamine",'Overlays':"Superpositiones",'Base Layer':"Strato de base",'noFID':"Non pote actualisar un elemento sin FID.",'browserNotSupported':"Tu navigator non supporta le rendition de vectores. Le renditores actualmente supportate es:\n${renderers}",'minZoomLevelError':"Le proprietate minZoomLevel es solmente pro uso con le stratos descendente de FixedZoomLevels. Le facto que iste strato WFS verifica minZoomLevel es un reliquia del passato. Nonobstante, si nos lo remove immediatemente, nos pote rumper applicationes a base de OL que depende de illo. Ergo nos lo declara obsolete; le verification de minZoomLevel in basso essera removite in version 3.0. Per favor usa in su loco le configuration de resolutiones min/max como describite a: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transaction WFS: SUCCESSO ${response}",'commitFailed':"Transaction WFS: FALLEVA ${response}",'googleWarning':"Le strato Google non poteva esser cargate correctemente.\x3cbr\x3e\x3cbr\x3ePro disfacer te de iste message, selige un nove BaseLayer in le selector de strato in alto a dextra.\x3cbr\x3e\x3cbr\x3eMulto probabilemente, isto es proque le script del libreria de Google Maps non esseva includite o non contine le clave API correcte pro tu sito.\x3cbr\x3e\x3cbr\x3eDisveloppatores: Pro adjuta de corriger isto, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclicca hic\x3c/a",'getLayerWarning':"Le strato ${layerType} non poteva esser cargate correctemente.\x3cbr\x3e\x3cbr\x3ePro disfacer te de iste message, selige un nove BaseLayer in le selector de strato in alto a dextra.\x3cbr\x3e\x3cbr\x3eMulto probabilemente, isto es proque le script del libreria de ${layerLib} non esseva correctemente includite.\x3cbr\x3e\x3cbr\x3eDisveloppatores: Pro adjuta de corriger isto, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclicca hic\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Scala = 1 : ${scaleDenom}",'W':"W",'E':"E",'N':"N",'S':"S",'reprojectDeprecated':"Tu usa le option \'reproject\' in le strato ${layerName} layer. Iste option es obsolescente: illo esseva pro poter monstrar datos super cartas de base commercial, ma iste functionalitate pote ora esser attingite con le uso de Spherical Mercator. Ulterior information es disponibile a http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Iste methodo ha essite declarate obsolescente e essera removite in version 3.0. Per favor usa ${newMethod} in su loco."});OpenLayers.Handler.Box=OpenLayers.Class(OpenLayers.Handler,{dragHandler:null,boxDivClassName:'olHandlerBoxZoomBox',boxOffsets:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);this.dragHandler=new OpenLayers.Handler.Drag(this,{down:this.startBox,move:this.moveBox,out:this.removeBox,up:this.endBox},{keyMask:this.keyMask});},destroy:function(){OpenLayers.Handler.prototype.destroy.apply(this,arguments);if(this.dragHandler){this.dragHandler.destroy();this.dragHandler=null;}},setMap:function(map){OpenLayers.Handler.prototype.setMap.apply(this,arguments);if(this.dragHandler){this.dragHandler.setMap(map);}},startBox:function(xy){this.callback("start",[]);this.zoomBox=OpenLayers.Util.createDiv('zoomBox',{x:-9999,y:-9999});this.zoomBox.className=this.boxDivClassName;this.zoomBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.viewPortDiv.appendChild(this.zoomBox);OpenLayers.Element.addClass(this.map.viewPortDiv,"olDrawBox");},moveBox:function(xy){var startX=this.dragHandler.start.x;var startY=this.dragHandler.start.y;var deltaX=Math.abs(startX-xy.x);var deltaY=Math.abs(startY-xy.y);var offset=this.getBoxOffsets();this.zoomBox.style.width=(deltaX+offset.width+1)+"px";this.zoomBox.style.height=(deltaY+offset.height+1)+"px";this.zoomBox.style.left=(xy.x<startX?startX-deltaX-offset.left:startX-offset.left)+"px";this.zoomBox.style.top=(xy.y<startY?startY-deltaY-offset.top:startY-offset.top)+"px";},endBox:function(end){var result;if(Math.abs(this.dragHandler.start.x-end.x)>5||Math.abs(this.dragHandler.start.y-end.y)>5){var start=this.dragHandler.start;var top=Math.min(start.y,end.y);var bottom=Math.max(start.y,end.y);var left=Math.min(start.x,end.x);var right=Math.max(start.x,end.x);result=new OpenLayers.Bounds(left,bottom,right,top);}else{result=this.dragHandler.start.clone();}
+this.removeBox();this.callback("done",[result]);},removeBox:function(){this.map.viewPortDiv.removeChild(this.zoomBox);this.zoomBox=null;this.boxOffsets=null;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDrawBox");},activate:function(){if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.dragHandler.activate();return true;}else{return false;}},deactivate:function(){if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){if(this.dragHandler.deactivate()){if(this.zoomBox){this.removeBox();}}
+return true;}else{return false;}},getBoxOffsets:function(){if(!this.boxOffsets){var testDiv=document.createElement("div");testDiv.style.position="absolute";testDiv.style.border="1px solid black";testDiv.style.width="3px";document.body.appendChild(testDiv);var w3cBoxModel=testDiv.clientWidth==3;document.body.removeChild(testDiv);var left=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-left-width"));var right=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-right-width"));var top=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-top-width"));var bottom=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-bottom-width"));this.boxOffsets={left:left,right:right,top:top,bottom:bottom,width:w3cBoxModel===false?left+right:0,height:w3cBoxModel===false?top+bottom:0};}
+return this.boxOffsets;},CLASS_NAME:"OpenLayers.Handler.Box"});OpenLayers.Control.ZoomBox=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,out:false,keyMask:null,alwaysZoom:false,draw:function(){this.handler=new OpenLayers.Handler.Box(this,{done:this.zoomBox},{keyMask:this.keyMask});},zoomBox:function(position){if(position instanceof OpenLayers.Bounds){var bounds;if(!this.out){var minXY=this.map.getLonLatFromPixel({x:position.left,y:position.bottom});var maxXY=this.map.getLonLatFromPixel({x:position.right,y:position.top});bounds=new OpenLayers.Bounds(minXY.lon,minXY.lat,maxXY.lon,maxXY.lat);}else{var pixWidth=Math.abs(position.right-position.left);var pixHeight=Math.abs(position.top-position.bottom);var zoomFactor=Math.min((this.map.size.h/pixHeight),(this.map.size.w/pixWidth));var extent=this.map.getExtent();var center=this.map.getLonLatFromPixel(position.getCenterPixel());var xmin=center.lon-(extent.getWidth()/2)*zoomFactor;var xmax=center.lon+(extent.getWidth()/2)*zoomFactor;var ymin=center.lat-(extent.getHeight()/2)*zoomFactor;var ymax=center.lat+(extent.getHeight()/2)*zoomFactor;bounds=new OpenLayers.Bounds(xmin,ymin,xmax,ymax);}
+var lastZoom=this.map.getZoom();this.map.zoomToExtent(bounds);if(lastZoom==this.map.getZoom()&&this.alwaysZoom==true){this.map.zoomTo(lastZoom+(this.out?-1:1));}}else{if(!this.out){this.map.setCenter(this.map.getLonLatFromPixel(position),this.map.getZoom()+1);}else{this.map.setCenter(this.map.getLonLatFromPixel(position),this.map.getZoom()-1);}}},CLASS_NAME:"OpenLayers.Control.ZoomBox"});OpenLayers.Control.DragPan=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,panned:false,interval:1,documentDrag:false,kinetic:null,enableKinetic:false,kineticInterval:10,draw:function(){if(this.enableKinetic){var config={interval:this.kineticInterval};if(typeof this.enableKinetic==="object"){config=OpenLayers.Util.extend(config,this.enableKinetic);}
+this.kinetic=new OpenLayers.Kinetic(config);}
+this.handler=new OpenLayers.Handler.Drag(this,{"move":this.panMap,"done":this.panMapDone,"down":this.panMapStart},{interval:this.interval,documentDrag:this.documentDrag});},panMapStart:function(){if(this.kinetic){this.kinetic.begin();}},panMap:function(xy){if(this.kinetic){this.kinetic.update(xy);}
+this.panned=true;this.map.pan(this.handler.last.x-xy.x,this.handler.last.y-xy.y,{dragging:true,animate:false});},panMapDone:function(xy){if(this.panned){var res=null;if(this.kinetic){res=this.kinetic.end(xy);}
+this.map.pan(this.handler.last.x-xy.x,this.handler.last.y-xy.y,{dragging:!!res,animate:false});if(res){var self=this;this.kinetic.move(res,function(x,y,end){self.map.pan(x,y,{dragging:!end,animate:false});});}
+this.panned=false;}},CLASS_NAME:"OpenLayers.Control.DragPan"});OpenLayers.Handler.Click=OpenLayers.Class(OpenLayers.Handler,{delay:300,single:true,'double':false,pixelTolerance:0,dblclickTolerance:13,stopSingle:false,stopDouble:false,timerId:null,touch:false,down:null,last:null,first:null,rightclickTimerId:null,touchstart:function(evt){if(!this.touch){this.unregisterMouseListeners();this.touch=true;}
+this.down=this.getEventInfo(evt);this.last=this.getEventInfo(evt);return true;},touchmove:function(evt){this.last=this.getEventInfo(evt);return true;},touchend:function(evt){if(this.down){evt.xy=this.last.xy;evt.lastTouches=this.last.touches;this.handleSingle(evt);this.down=null;}
+return true;},unregisterMouseListeners:function(){this.map.events.un({mousedown:this.mousedown,mouseup:this.mouseup,click:this.click,dblclick:this.dblclick,scope:this});},mousedown:function(evt){this.down=this.getEventInfo(evt);this.last=this.getEventInfo(evt);return true;},mouseup:function(evt){var propagate=true;if(this.checkModifiers(evt)&&this.control.handleRightClicks&&OpenLayers.Event.isRightClick(evt)){propagate=this.rightclick(evt);}
+return propagate;},rightclick:function(evt){if(this.passesTolerance(evt)){if(this.rightclickTimerId!=null){this.clearTimer();this.callback('dblrightclick',[evt]);return!this.stopDouble;}else{var clickEvent=this['double']?OpenLayers.Util.extend({},evt):this.callback('rightclick',[evt]);var delayedRightCall=OpenLayers.Function.bind(this.delayedRightCall,this,clickEvent);this.rightclickTimerId=window.setTimeout(delayedRightCall,this.delay);}}
+return!this.stopSingle;},delayedRightCall:function(evt){this.rightclickTimerId=null;if(evt){this.callback('rightclick',[evt]);}},click:function(evt){if(!this.last){this.last=this.getEventInfo(evt);}
+this.handleSingle(evt);return!this.stopSingle;},dblclick:function(evt){this.handleDouble(evt);return!this.stopDouble;},handleDouble:function(evt){if(this.passesDblclickTolerance(evt)){if(this["double"]){this.callback("dblclick",[evt]);}
+this.clearTimer();}},handleSingle:function(evt){if(this.passesTolerance(evt)){if(this.timerId!=null){if(this.last.touches&&this.last.touches.length===1){if(this["double"]){OpenLayers.Event.stop(evt);}
+this.handleDouble(evt);}
+if(!this.last.touches||this.last.touches.length!==2){this.clearTimer();}}else{this.first=this.getEventInfo(evt);var clickEvent=this.single?OpenLayers.Util.extend({},evt):null;this.queuePotentialClick(clickEvent);}}},queuePotentialClick:function(evt){this.timerId=window.setTimeout(OpenLayers.Function.bind(this.delayedCall,this,evt),this.delay);},passesTolerance:function(evt){var passes=true;if(this.pixelTolerance!=null&&this.down&&this.down.xy){passes=this.pixelTolerance>=this.down.xy.distanceTo(evt.xy);if(passes&&this.touch&&this.down.touches.length===this.last.touches.length){for(var i=0,ii=this.down.touches.length;i<ii;++i){if(this.getTouchDistance(this.down.touches[i],this.last.touches[i])>this.pixelTolerance){passes=false;break;}}}}
+return passes;},getTouchDistance:function(from,to){return Math.sqrt(Math.pow(from.clientX-to.clientX,2)+
+Math.pow(from.clientY-to.clientY,2));},passesDblclickTolerance:function(evt){var passes=true;if(this.down&&this.first){passes=this.down.xy.distanceTo(this.first.xy)<=this.dblclickTolerance;}
+return passes;},clearTimer:function(){if(this.timerId!=null){window.clearTimeout(this.timerId);this.timerId=null;}
+if(this.rightclickTimerId!=null){window.clearTimeout(this.rightclickTimerId);this.rightclickTimerId=null;}},delayedCall:function(evt){this.timerId=null;if(evt){this.callback("click",[evt]);}},getEventInfo:function(evt){var touches;if(evt.touches){var len=evt.touches.length;touches=new Array(len);var touch;for(var i=0;i<len;i++){touch=evt.touches[i];touches[i]={clientX:touch.clientX,clientY:touch.clientY};}}
+return{xy:evt.xy,touches:touches};},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.clearTimer();this.down=null;this.first=null;this.last=null;this.touch=false;deactivated=true;}
+return deactivated;},CLASS_NAME:"OpenLayers.Handler.Click"});OpenLayers.Control.Navigation=OpenLayers.Class(OpenLayers.Control,{dragPan:null,dragPanOptions:null,pinchZoom:null,pinchZoomOptions:null,documentDrag:false,zoomBox:null,zoomBoxEnabled:true,zoomWheelEnabled:true,mouseWheelOptions:null,handleRightClicks:false,zoomBoxKeyMask:OpenLayers.Handler.MOD_SHIFT,autoActivate:true,initialize:function(options){this.handlers={};OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){this.deactivate();if(this.dragPan){this.dragPan.destroy();}
+this.dragPan=null;if(this.zoomBox){this.zoomBox.destroy();}
+this.zoomBox=null;if(this.pinchZoom){this.pinchZoom.destroy();}
+this.pinchZoom=null;OpenLayers.Control.prototype.destroy.apply(this,arguments);},activate:function(){this.dragPan.activate();if(this.zoomWheelEnabled){this.handlers.wheel.activate();}
+this.handlers.click.activate();if(this.zoomBoxEnabled){this.zoomBox.activate();}
+if(this.pinchZoom){this.pinchZoom.activate();}
+return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){if(this.pinchZoom){this.pinchZoom.deactivate();}
+this.zoomBox.deactivate();this.dragPan.deactivate();this.handlers.click.deactivate();this.handlers.wheel.deactivate();return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},draw:function(){if(this.handleRightClicks){this.map.viewPortDiv.oncontextmenu=OpenLayers.Function.False;}
+var clickCallbacks={'click':this.defaultClick,'dblclick':this.defaultDblClick,'dblrightclick':this.defaultDblRightClick};var clickOptions={'double':true,'stopDouble':true};this.handlers.click=new OpenLayers.Handler.Click(this,clickCallbacks,clickOptions);this.dragPan=new OpenLayers.Control.DragPan(OpenLayers.Util.extend({map:this.map,documentDrag:this.documentDrag},this.dragPanOptions));this.zoomBox=new OpenLayers.Control.ZoomBox({map:this.map,keyMask:this.zoomBoxKeyMask});this.dragPan.draw();this.zoomBox.draw();this.handlers.wheel=new OpenLayers.Handler.MouseWheel(this,{"up":this.wheelUp,"down":this.wheelDown},this.mouseWheelOptions);if(OpenLayers.Control.PinchZoom){this.pinchZoom=new OpenLayers.Control.PinchZoom(OpenLayers.Util.extend({map:this.map},this.pinchZoomOptions));}},defaultClick:function(evt){if(evt.lastTouches&&evt.lastTouches.length==2){this.map.zoomOut();}},defaultDblClick:function(evt){var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom+1);},defaultDblRightClick:function(evt){var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom-1);},wheelChange:function(evt,deltaZ){var currentZoom=this.map.getZoom();var newZoom=this.map.getZoom()+Math.round(deltaZ);newZoom=Math.max(newZoom,0);newZoom=Math.min(newZoom,this.map.getNumZoomLevels());if(newZoom===currentZoom){return;}
+var size=this.map.getSize();var deltaX=size.w/2-evt.xy.x;var deltaY=evt.xy.y-size.h/2;var newRes=this.map.baseLayer.getResolutionForZoom(newZoom);var zoomPoint=this.map.getLonLatFromPixel(evt.xy);var newCenter=new OpenLayers.LonLat(zoomPoint.lon+deltaX*newRes,zoomPoint.lat+deltaY*newRes);this.map.setCenter(newCenter,newZoom);},wheelUp:function(evt,delta){this.wheelChange(evt,delta||1);},wheelDown:function(evt,delta){this.wheelChange(evt,delta||-1);},disableZoomBox:function(){this.zoomBoxEnabled=false;this.zoomBox.deactivate();},enableZoomBox:function(){this.zoomBoxEnabled=true;if(this.active){this.zoomBox.activate();}},disableZoomWheel:function(){this.zoomWheelEnabled=false;this.handlers.wheel.deactivate();},enableZoomWheel:function(){this.zoomWheelEnabled=true;if(this.active){this.handlers.wheel.activate();}},CLASS_NAME:"OpenLayers.Control.Navigation"});OpenLayers.Lang["sk"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Neobslúžené požiadavky vracajú ${statusText}",'Permalink':"Trvalý odkaz",'Overlays':"Prekrytia",'Base Layer':"Základná vrstva",'noFID':"Nie je možné aktualizovať vlastnosť, pre ktorú neexistuje FID.",'browserNotSupported':"Váš prehliadač nepodporuje vykresľovanie vektorov. Momentálne podporované vykresľovače sú:\n${renderers}",'minZoomLevelError':"Vlastnosť minZoomLevel je určený iba na použitie s vrstvami odvodenými od FixedZoomLevels. To, že táto wfs vrstva kontroluje minZoomLevel je pozostatok z minulosti. Nemôžeme ho však odstrániť, aby sme sa vyhli možnému porušeniu aplikácií založených na Open Layers, ktoré na tomto môže závisieť. Preto ho označujeme ako zavrhovaný - dolu uvedená kontrola minZoomLevel bude odstránená vo verzii 3.0. Použite prosím namiesto toho kontrolu min./max. rozlíšenia podľa tu uvedeného popisu: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transakcia WFS: ÚSPEŠNÁ ${response}",'commitFailed':"Transakcia WFS: ZLYHALA ${response}",'googleWarning':"Vrstvu Google nebolo možné správne načítať.\x3cbr\x3e\x3cbr\x3eAby ste sa tejto správy zbavili vyberte novú BaseLayer v prepínači vrstiev v pravom hornom rohu.\x3cbr\x3e\x3cbr\x3eToto sa stalo pravdepodobne preto, že skript knižnice Google Maps buď nebol načítaný alebo neobsahuje správny kľúč API pre vašu lokalitu.\x3cbr\x3e\x3cbr\x3eVývojári: Tu môžete získať \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3epomoc so sfunkčnením\x3c/a\x3e",'getLayerWarning':"Vrstvu ${layerType} nebolo možné správne načítať.\x3cbr\x3e\x3cbr\x3eAby ste sa tejto správy zbavili vyberte novú BaseLayer v prepínači vrstiev v pravom hornom rohu.\x3cbr\x3e\x3cbr\x3eToto sa stalo pravdepodobne preto, že skript knižnice ${layerType} buď nebol načítaný alebo neobsahuje správny kľúč API pre vašu lokalitu.\x3cbr\x3e\x3cbr\x3eVývojári: Tu môžete získať \x3ca href=\'http://trac.openlayers.org/wiki/${layerType}\' target=\'_blank\'\x3epomoc so sfunkčnením\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Mierka = 1 : ${scaleDenom}",'reprojectDeprecated':"Používate voľby „reproject“ vrstvy ${layerType}. Táto voľba je zzavrhovaná: jej použitie bolo navrhnuté na podporu zobrazovania údajov nad komerčnými základovými mapami, ale túto funkcionalitu je teraz možné dosiahnuť pomocou Spherical Mercator. Ďalšie informácie získate na stránke http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Táto metóda je zavrhovaná a bude odstránená vo verzii 3.0. Použite prosím namiesto nej metódu ${newMethod}."});OpenLayers.Renderer.SVG=OpenLayers.Class(OpenLayers.Renderer.Elements,{xmlns:"http://www.w3.org/2000/svg",xlinkns:"http://www.w3.org/1999/xlink",MAX_PIXEL:15000,translationParameters:null,symbolMetrics:null,initialize:function(containerID){if(!this.supported()){return;}
+OpenLayers.Renderer.Elements.prototype.initialize.apply(this,arguments);this.translationParameters={x:0,y:0};this.symbolMetrics={};},supported:function(){var svgFeature="http://www.w3.org/TR/SVG11/feature#";return(document.implementation&&(document.implementation.hasFeature("org.w3c.svg","1.0")||document.implementation.hasFeature(svgFeature+"SVG","1.1")||document.implementation.hasFeature(svgFeature+"BasicStructure","1.1")));},inValidRange:function(x,y,xyOnly){var left=x+(xyOnly?0:this.translationParameters.x);var top=y+(xyOnly?0:this.translationParameters.y);return(left>=-this.MAX_PIXEL&&left<=this.MAX_PIXEL&&top>=-this.MAX_PIXEL&&top<=this.MAX_PIXEL);},setExtent:function(extent,resolutionChanged){var coordSysUnchanged=OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,arguments);var resolution=this.getResolution(),left=-extent.left/resolution,top=extent.top/resolution;if(resolutionChanged){this.left=left;this.top=top;var extentString="0 0 "+this.size.w+" "+this.size.h;this.rendererRoot.setAttributeNS(null,"viewBox",extentString);this.translate(this.xOffset,0);return true;}else{var inRange=this.translate(left-this.left+this.xOffset,top-this.top);if(!inRange){this.setExtent(extent,true);}
+return coordSysUnchanged&&inRange;}},translate:function(x,y){if(!this.inValidRange(x,y,true)){return false;}else{var transformString="";if(x||y){transformString="translate("+x+","+y+")";}
+this.root.setAttributeNS(null,"transform",transformString);this.translationParameters={x:x,y:y};return true;}},setSize:function(size){OpenLayers.Renderer.prototype.setSize.apply(this,arguments);this.rendererRoot.setAttributeNS(null,"width",this.size.w);this.rendererRoot.setAttributeNS(null,"height",this.size.h);},getNodeType:function(geometry,style){var nodeType=null;switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":if(style.externalGraphic){nodeType="image";}else if(this.isComplexSymbol(style.graphicName)){nodeType="svg";}else{nodeType="circle";}
+break;case"OpenLayers.Geometry.Rectangle":nodeType="rect";break;case"OpenLayers.Geometry.LineString":nodeType="polyline";break;case"OpenLayers.Geometry.LinearRing":nodeType="polygon";break;case"OpenLayers.Geometry.Polygon":case"OpenLayers.Geometry.Curve":nodeType="path";break;default:break;}
+return nodeType;},setStyle:function(node,style,options){style=style||node._style;options=options||node._options;var r=parseFloat(node.getAttributeNS(null,"r"));var widthFactor=1;var pos;if(node._geometryClass=="OpenLayers.Geometry.Point"&&r){node.style.visibility="";if(style.graphic===false){node.style.visibility="hidden";}else if(style.externalGraphic){pos=this.getPosition(node);if(style.graphicTitle){node.setAttributeNS(null,"title",style.graphicTitle);var titleNode=node.getElementsByTagName("title");if(titleNode.length>0){titleNode[0].firstChild.textContent=style.graphicTitle;}else{var label=this.nodeFactory(null,"title");label.textContent=style.graphicTitle;node.appendChild(label);}}
+if(style.graphicWidth&&style.graphicHeight){node.setAttributeNS(null,"preserveAspectRatio","none");}
+var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset:-(0.5*height);var opacity=style.graphicOpacity||style.fillOpacity;node.setAttributeNS(null,"x",(pos.x+xOffset).toFixed());node.setAttributeNS(null,"y",(pos.y+yOffset).toFixed());node.setAttributeNS(null,"width",width);node.setAttributeNS(null,"height",height);node.setAttributeNS(this.xlinkns,"href",style.externalGraphic);node.setAttributeNS(null,"style","opacity: "+opacity);node.onclick=OpenLayers.Renderer.SVG.preventDefault;}else if(this.isComplexSymbol(style.graphicName)){var offset=style.pointRadius*3;var size=offset*2;var src=this.importSymbol(style.graphicName);pos=this.getPosition(node);widthFactor=this.symbolMetrics[src.id][0]*3/size;var parent=node.parentNode;var nextSibling=node.nextSibling;if(parent){parent.removeChild(node);}
+node.firstChild&&node.removeChild(node.firstChild);node.appendChild(src.firstChild.cloneNode(true));node.setAttributeNS(null,"viewBox",src.getAttributeNS(null,"viewBox"));node.setAttributeNS(null,"width",size);node.setAttributeNS(null,"height",size);node.setAttributeNS(null,"x",pos.x-offset);node.setAttributeNS(null,"y",pos.y-offset);if(nextSibling){parent.insertBefore(node,nextSibling);}else if(parent){parent.appendChild(node);}}else{node.setAttributeNS(null,"r",style.pointRadius);}
+var rotation=style.rotation;if((rotation!==undefined||node._rotation!==undefined)&&pos){node._rotation=rotation;rotation|=0;if(node.nodeName!=="svg"){node.setAttributeNS(null,"transform","rotate("+rotation+" "+pos.x+" "+
+pos.y+")");}else{var metrics=this.symbolMetrics[src.id];node.firstChild.setAttributeNS(null,"transform","rotate("
++rotation+" "
++metrics[1]+" "
++metrics[2]+")");}}}
+if(options.isFilled){node.setAttributeNS(null,"fill",style.fillColor);node.setAttributeNS(null,"fill-opacity",style.fillOpacity);}else{node.setAttributeNS(null,"fill","none");}
+if(options.isStroked){node.setAttributeNS(null,"stroke",style.strokeColor);node.setAttributeNS(null,"stroke-opacity",style.strokeOpacity);node.setAttributeNS(null,"stroke-width",style.strokeWidth*widthFactor);node.setAttributeNS(null,"stroke-linecap",style.strokeLinecap||"round");node.setAttributeNS(null,"stroke-linejoin","round");style.strokeDashstyle&&node.setAttributeNS(null,"stroke-dasharray",this.dashStyle(style,widthFactor));}else{node.setAttributeNS(null,"stroke","none");}
+if(style.pointerEvents){node.setAttributeNS(null,"pointer-events",style.pointerEvents);}
+if(style.cursor!=null){node.setAttributeNS(null,"cursor",style.cursor);}
+return node;},dashStyle:function(style,widthFactor){var w=style.strokeWidth*widthFactor;var str=style.strokeDashstyle;switch(str){case'solid':return'none';case'dot':return[1,4*w].join();case'dash':return[4*w,4*w].join();case'dashdot':return[4*w,4*w,1,4*w].join();case'longdash':return[8*w,4*w].join();case'longdashdot':return[8*w,4*w,1,4*w].join();default:return OpenLayers.String.trim(str).replace(/\s+/g,",");}},createNode:function(type,id){var node=document.createElementNS(this.xmlns,type);if(id){node.setAttributeNS(null,"id",id);}
+return node;},nodeTypeCompare:function(node,type){return(type==node.nodeName);},createRenderRoot:function(){var svg=this.nodeFactory(this.container.id+"_svgRoot","svg");svg.style.display="block";return svg;},createRoot:function(suffix){return this.nodeFactory(this.container.id+suffix,"g");},createDefs:function(){var defs=this.nodeFactory(this.container.id+"_defs","defs");this.rendererRoot.appendChild(defs);return defs;},drawPoint:function(node,geometry){return this.drawCircle(node,geometry,1);},drawCircle:function(node,geometry,radius){var resolution=this.getResolution();var x=((geometry.x-this.featureDx)/resolution+this.left);var y=(this.top-geometry.y/resolution);if(this.inValidRange(x,y)){node.setAttributeNS(null,"cx",x);node.setAttributeNS(null,"cy",y);node.setAttributeNS(null,"r",radius);return node;}else{return false;}},drawLineString:function(node,geometry){var componentsResult=this.getComponentsString(geometry.components);if(componentsResult.path){node.setAttributeNS(null,"points",componentsResult.path);return(componentsResult.complete?node:null);}else{return false;}},drawLinearRing:function(node,geometry){var componentsResult=this.getComponentsString(geometry.components);if(componentsResult.path){node.setAttributeNS(null,"points",componentsResult.path);return(componentsResult.complete?node:null);}else{return false;}},drawPolygon:function(node,geometry){var d="";var draw=true;var complete=true;var linearRingResult,path;for(var j=0,len=geometry.components.length;j<len;j++){d+=" M";linearRingResult=this.getComponentsString(geometry.components[j].components," ");path=linearRingResult.path;if(path){d+=" "+path;complete=linearRingResult.complete&&complete;}else{draw=false;}}
+d+=" z";if(draw){node.setAttributeNS(null,"d",d);node.setAttributeNS(null,"fill-rule","evenodd");return complete?node:null;}else{return false;}},drawRectangle:function(node,geometry){var resolution=this.getResolution();var x=((geometry.x-this.featureDx)/resolution+this.left);var y=(this.top-geometry.y/resolution);if(this.inValidRange(x,y)){node.setAttributeNS(null,"x",x);node.setAttributeNS(null,"y",y);node.setAttributeNS(null,"width",geometry.width/resolution);node.setAttributeNS(null,"height",geometry.height/resolution);return node;}else{return false;}},drawText:function(featureId,style,location){var drawOutline=(!!style.labelOutlineWidth);if(drawOutline){var outlineStyle=OpenLayers.Util.extend({},style);outlineStyle.fontColor=outlineStyle.labelOutlineColor;outlineStyle.fontStrokeColor=outlineStyle.labelOutlineColor;outlineStyle.fontStrokeWidth=style.labelOutlineWidth;delete outlineStyle.labelOutlineWidth;this.drawText(featureId,outlineStyle,location);}
+var resolution=this.getResolution();var x=((location.x-this.featureDx)/resolution+this.left);var y=(location.y/resolution-this.top);var suffix=(drawOutline)?this.LABEL_OUTLINE_SUFFIX:this.LABEL_ID_SUFFIX;var label=this.nodeFactory(featureId+suffix,"text");label.setAttributeNS(null,"x",x);label.setAttributeNS(null,"y",-y);if(style.fontColor){label.setAttributeNS(null,"fill",style.fontColor);}
+if(style.fontStrokeColor){label.setAttributeNS(null,"stroke",style.fontStrokeColor);}
+if(style.fontStrokeWidth){label.setAttributeNS(null,"stroke-width",style.fontStrokeWidth);}
+if(style.fontOpacity){label.setAttributeNS(null,"opacity",style.fontOpacity);}
+if(style.fontFamily){label.setAttributeNS(null,"font-family",style.fontFamily);}
+if(style.fontSize){label.setAttributeNS(null,"font-size",style.fontSize);}
+if(style.fontWeight){label.setAttributeNS(null,"font-weight",style.fontWeight);}
+if(style.fontStyle){label.setAttributeNS(null,"font-style",style.fontStyle);}
+if(style.labelSelect===true){label.setAttributeNS(null,"pointer-events","visible");label._featureId=featureId;}else{label.setAttributeNS(null,"pointer-events","none");}
+var align=style.labelAlign||OpenLayers.Renderer.defaultSymbolizer.labelAlign;label.setAttributeNS(null,"text-anchor",OpenLayers.Renderer.SVG.LABEL_ALIGN[align[0]]||"middle");if(OpenLayers.IS_GECKO===true){label.setAttributeNS(null,"dominant-baseline",OpenLayers.Renderer.SVG.LABEL_ALIGN[align[1]]||"central");}
+var labelRows=style.label.split('\n');var numRows=labelRows.length;while(label.childNodes.length>numRows){label.removeChild(label.lastChild);}
+for(var i=0;i<numRows;i++){var tspan=this.nodeFactory(featureId+suffix+"_tspan_"+i,"tspan");if(style.labelSelect===true){tspan._featureId=featureId;tspan._geometry=location;tspan._geometryClass=location.CLASS_NAME;}
+if(OpenLayers.IS_GECKO===false){tspan.setAttributeNS(null,"baseline-shift",OpenLayers.Renderer.SVG.LABEL_VSHIFT[align[1]]||"-35%");}
+tspan.setAttribute("x",x);if(i==0){var vfactor=OpenLayers.Renderer.SVG.LABEL_VFACTOR[align[1]];if(vfactor==null){vfactor=-.5;}
+tspan.setAttribute("dy",(vfactor*(numRows-1))+"em");}else{tspan.setAttribute("dy","1em");}
+tspan.textContent=(labelRows[i]==='')?' ':labelRows[i];if(!tspan.parentNode){label.appendChild(tspan);}}
+if(!label.parentNode){this.textRoot.appendChild(label);}},getComponentsString:function(components,separator){var renderCmp=[];var complete=true;var len=components.length;var strings=[];var str,component;for(var i=0;i<len;i++){component=components[i];renderCmp.push(component);str=this.getShortString(component);if(str){strings.push(str);}else{if(i>0){if(this.getShortString(components[i-1])){strings.push(this.clipLine(components[i],components[i-1]));}}
+if(i<len-1){if(this.getShortString(components[i+1])){strings.push(this.clipLine(components[i],components[i+1]));}}
+complete=false;}}
+return{path:strings.join(separator||","),complete:complete};},clipLine:function(badComponent,goodComponent){if(goodComponent.equals(badComponent)){return"";}
+var resolution=this.getResolution();var maxX=this.MAX_PIXEL-this.translationParameters.x;var maxY=this.MAX_PIXEL-this.translationParameters.y;var x1=(goodComponent.x-this.featureDx)/resolution+this.left;var y1=this.top-goodComponent.y/resolution;var x2=(badComponent.x-this.featureDx)/resolution+this.left;var y2=this.top-badComponent.y/resolution;var k;if(x2<-maxX||x2>maxX){k=(y2-y1)/(x2-x1);x2=x2<0?-maxX:maxX;y2=y1+(x2-x1)*k;}
+if(y2<-maxY||y2>maxY){k=(x2-x1)/(y2-y1);y2=y2<0?-maxY:maxY;x2=x1+(y2-y1)*k;}
+return x2+","+y2;},getShortString:function(point){var resolution=this.getResolution();var x=((point.x-this.featureDx)/resolution+this.left);var y=(this.top-point.y/resolution);if(this.inValidRange(x,y)){return x+","+y;}else{return false;}},getPosition:function(node){return({x:parseFloat(node.getAttributeNS(null,"cx")),y:parseFloat(node.getAttributeNS(null,"cy"))});},importSymbol:function(graphicName){if(!this.defs){this.defs=this.createDefs();}
+var id=this.container.id+"-"+graphicName;var existing=document.getElementById(id);if(existing!=null){return existing;}
+var symbol=OpenLayers.Renderer.symbol[graphicName];if(!symbol){throw new Error(graphicName+' is not a valid symbol name');}
+var symbolNode=this.nodeFactory(id,"symbol");var node=this.nodeFactory(null,"polygon");symbolNode.appendChild(node);var symbolExtent=new OpenLayers.Bounds(Number.MAX_VALUE,Number.MAX_VALUE,0,0);var points=[];var x,y;for(var i=0;i<symbol.length;i=i+2){x=symbol[i];y=symbol[i+1];symbolExtent.left=Math.min(symbolExtent.left,x);symbolExtent.bottom=Math.min(symbolExtent.bottom,y);symbolExtent.right=Math.max(symbolExtent.right,x);symbolExtent.top=Math.max(symbolExtent.top,y);points.push(x,",",y);}
+node.setAttributeNS(null,"points",points.join(" "));var width=symbolExtent.getWidth();var height=symbolExtent.getHeight();var viewBox=[symbolExtent.left-width,symbolExtent.bottom-height,width*3,height*3];symbolNode.setAttributeNS(null,"viewBox",viewBox.join(" "));this.symbolMetrics[id]=[Math.max(width,height),symbolExtent.getCenterLonLat().lon,symbolExtent.getCenterLonLat().lat];this.defs.appendChild(symbolNode);return symbolNode;},getFeatureIdFromEvent:function(evt){var featureId=OpenLayers.Renderer.Elements.prototype.getFeatureIdFromEvent.apply(this,arguments);if(!featureId){var target=evt.target;featureId=target.parentNode&&target!=this.rendererRoot?target.parentNode._featureId:undefined;}
+return featureId;},CLASS_NAME:"OpenLayers.Renderer.SVG"});OpenLayers.Renderer.SVG.LABEL_ALIGN={"l":"start","r":"end","b":"bottom","t":"hanging"};OpenLayers.Renderer.SVG.LABEL_VSHIFT={"t":"-70%","b":"0"};OpenLayers.Renderer.SVG.LABEL_VFACTOR={"t":0,"b":-1};OpenLayers.Renderer.SVG.preventDefault=function(e){e.preventDefault&&e.preventDefault();};OpenLayers.Control.ScaleLine=OpenLayers.Class(OpenLayers.Control,{maxWidth:100,topOutUnits:"km",topInUnits:"m",bottomOutUnits:"mi",bottomInUnits:"ft",eTop:null,eBottom:null,geodesic:false,draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.eTop){this.eTop=document.createElement("div");this.eTop.className=this.displayClass+"Top";var theLen=this.topInUnits.length;this.div.appendChild(this.eTop);if((this.topOutUnits=="")||(this.topInUnits=="")){this.eTop.style.visibility="hidden";}else{this.eTop.style.visibility="visible";}
+this.eBottom=document.createElement("div");this.eBottom.className=this.displayClass+"Bottom";this.div.appendChild(this.eBottom);if((this.bottomOutUnits=="")||(this.bottomInUnits=="")){this.eBottom.style.visibility="hidden";}else{this.eBottom.style.visibility="visible";}}
+this.map.events.register('moveend',this,this.update);this.update();return this.div;},getBarLen:function(maxLen){var digits=parseInt(Math.log(maxLen)/Math.log(10));var pow10=Math.pow(10,digits);var firstChar=parseInt(maxLen/pow10);var barLen;if(firstChar>5){barLen=5;}else if(firstChar>2){barLen=2;}else{barLen=1;}
+return barLen*pow10;},update:function(){var res=this.map.getResolution();if(!res){return;}
+var curMapUnits=this.map.getUnits();var inches=OpenLayers.INCHES_PER_UNIT;var maxSizeData=this.maxWidth*res*inches[curMapUnits];var geodesicRatio=1;if(this.geodesic===true){var maxSizeGeodesic=(this.map.getGeodesicPixelSize().w||0.000001)*this.maxWidth;var maxSizeKilometers=maxSizeData/inches["km"];geodesicRatio=maxSizeGeodesic/maxSizeKilometers;maxSizeData*=geodesicRatio;}
+var topUnits;var bottomUnits;if(maxSizeData>100000){topUnits=this.topOutUnits;bottomUnits=this.bottomOutUnits;}else{topUnits=this.topInUnits;bottomUnits=this.bottomInUnits;}
+var topMax=maxSizeData/inches[topUnits];var bottomMax=maxSizeData/inches[bottomUnits];var topRounded=this.getBarLen(topMax);var bottomRounded=this.getBarLen(bottomMax);topMax=topRounded/inches[curMapUnits]*inches[topUnits];bottomMax=bottomRounded/inches[curMapUnits]*inches[bottomUnits];var topPx=topMax/res/geodesicRatio;var bottomPx=bottomMax/res/geodesicRatio;if(this.eBottom.style.visibility=="visible"){this.eBottom.style.width=Math.round(bottomPx)+"px";this.eBottom.innerHTML=bottomRounded+" "+bottomUnits;}
+if(this.eTop.style.visibility=="visible"){this.eTop.style.width=Math.round(topPx)+"px";this.eTop.innerHTML=topRounded+" "+topUnits;}},CLASS_NAME:"OpenLayers.Control.ScaleLine"});OpenLayers.Icon=OpenLayers.Class({url:null,size:null,offset:null,calculateOffset:null,imageDiv:null,px:null,initialize:function(url,size,offset,calculateOffset){this.url=url;this.size=size||{w:20,h:20};this.offset=offset||{x:-(this.size.w/2),y:-(this.size.h/2)};this.calculateOffset=calculateOffset;var id=OpenLayers.Util.createUniqueID("OL_Icon_");this.imageDiv=OpenLayers.Util.createAlphaImageDiv(id);},destroy:function(){this.erase();OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild);this.imageDiv.innerHTML="";this.imageDiv=null;},clone:function(){return new OpenLayers.Icon(this.url,this.size,this.offset,this.calculateOffset);},setSize:function(size){if(size!=null){this.size=size;}
+this.draw();},setUrl:function(url){if(url!=null){this.url=url;}
+this.draw();},draw:function(px){OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,null,this.size,this.url,"absolute");this.moveTo(px);return this.imageDiv;},erase:function(){if(this.imageDiv!=null&&this.imageDiv.parentNode!=null){OpenLayers.Element.remove(this.imageDiv);}},setOpacity:function(opacity){OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,null,null,null,null,null,null,opacity);},moveTo:function(px){if(px!=null){this.px=px;}
+if(this.imageDiv!=null){if(this.px==null){this.display(false);}else{if(this.calculateOffset){this.offset=this.calculateOffset(this.size);}
+OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,{x:this.px.x+this.offset.x,y:this.px.y+this.offset.y});}}},display:function(display){this.imageDiv.style.display=(display)?"":"none";},isDrawn:function(){var isDrawn=(this.imageDiv&&this.imageDiv.parentNode&&(this.imageDiv.parentNode.nodeType!=11));return isDrawn;},CLASS_NAME:"OpenLayers.Icon"});OpenLayers.Marker=OpenLayers.Class({icon:null,lonlat:null,events:null,map:null,initialize:function(lonlat,icon){this.lonlat=lonlat;var newIcon=(icon)?icon:OpenLayers.Marker.defaultIcon();if(this.icon==null){this.icon=newIcon;}else{this.icon.url=newIcon.url;this.icon.size=newIcon.size;this.icon.offset=newIcon.offset;this.icon.calculateOffset=newIcon.calculateOffset;}
+this.events=new OpenLayers.Events(this,this.icon.imageDiv);},destroy:function(){this.erase();this.map=null;this.events.destroy();this.events=null;if(this.icon!=null){this.icon.destroy();this.icon=null;}},draw:function(px){return this.icon.draw(px);},erase:function(){if(this.icon!=null){this.icon.erase();}},moveTo:function(px){if((px!=null)&&(this.icon!=null)){this.icon.moveTo(px);}
+this.lonlat=this.map.getLonLatFromLayerPx(px);},isDrawn:function(){var isDrawn=(this.icon&&this.icon.isDrawn());return isDrawn;},onScreen:function(){var onScreen=false;if(this.map){var screenBounds=this.map.getExtent();onScreen=screenBounds.containsLonLat(this.lonlat);}
+return onScreen;},inflate:function(inflate){if(this.icon){this.icon.setSize({w:this.icon.size.w*inflate,h:this.icon.size.h*inflate});}},setOpacity:function(opacity){this.icon.setOpacity(opacity);},setUrl:function(url){this.icon.setUrl(url);},display:function(display){this.icon.display(display);},CLASS_NAME:"OpenLayers.Marker"});OpenLayers.Marker.defaultIcon=function(){return new OpenLayers.Icon(OpenLayers.Util.getImageLocation("marker.png"),{w:21,h:25},{x:-10.5,y:-25});};OpenLayers.Format.JSON=OpenLayers.Class(OpenLayers.Format,{indent:"    ",space:" ",newline:"\n",level:0,pretty:false,nativeJSON:(function(){return!!(window.JSON&&typeof JSON.parse=="function"&&typeof JSON.stringify=="function");})(),read:function(json,filter){var object;if(this.nativeJSON){object=JSON.parse(json,filter);}else try{if(/^[\],:{}\s]*$/.test(json.replace(/\\["\\\/bfnrtu]/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){object=eval('('+json+')');if(typeof filter==='function'){function walk(k,v){if(v&&typeof v==='object'){for(var i in v){if(v.hasOwnProperty(i)){v[i]=walk(i,v[i]);}}}
+return filter(k,v);}
+object=walk('',object);}}}catch(e){}
+if(this.keepData){this.data=object;}
+return object;},write:function(value,pretty){this.pretty=!!pretty;var json=null;var type=typeof value;if(this.serialize[type]){try{json=(!this.pretty&&this.nativeJSON)?JSON.stringify(value):this.serialize[type].apply(this,[value]);}catch(err){OpenLayers.Console.error("Trouble serializing: "+err);}}
+return json;},writeIndent:function(){var pieces=[];if(this.pretty){for(var i=0;i<this.level;++i){pieces.push(this.indent);}}
+return pieces.join('');},writeNewline:function(){return(this.pretty)?this.newline:'';},writeSpace:function(){return(this.pretty)?this.space:'';},serialize:{'object':function(object){if(object==null){return"null";}
+if(object.constructor==Date){return this.serialize.date.apply(this,[object]);}
+if(object.constructor==Array){return this.serialize.array.apply(this,[object]);}
+var pieces=['{'];this.level+=1;var key,keyJSON,valueJSON;var addComma=false;for(key in object){if(object.hasOwnProperty(key)){keyJSON=OpenLayers.Format.JSON.prototype.write.apply(this,[key,this.pretty]);valueJSON=OpenLayers.Format.JSON.prototype.write.apply(this,[object[key],this.pretty]);if(keyJSON!=null&&valueJSON!=null){if(addComma){pieces.push(',');}
+pieces.push(this.writeNewline(),this.writeIndent(),keyJSON,':',this.writeSpace(),valueJSON);addComma=true;}}}
+this.level-=1;pieces.push(this.writeNewline(),this.writeIndent(),'}');return pieces.join('');},'array':function(array){var json;var pieces=['['];this.level+=1;for(var i=0,len=array.length;i<len;++i){json=OpenLayers.Format.JSON.prototype.write.apply(this,[array[i],this.pretty]);if(json!=null){if(i>0){pieces.push(',');}
+pieces.push(this.writeNewline(),this.writeIndent(),json);}}
+this.level-=1;pieces.push(this.writeNewline(),this.writeIndent(),']');return pieces.join('');},'string':function(string){var m={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};if(/["\\\x00-\x1f]/.test(string)){return'"'+string.replace(/([\x00-\x1f\\"])/g,function(a,b){var c=m[b];if(c){return c;}
+c=b.charCodeAt();return'\\u00'+
+Math.floor(c/16).toString(16)+
+(c%16).toString(16);})+'"';}
+return'"'+string+'"';},'number':function(number){return isFinite(number)?String(number):"null";},'boolean':function(bool){return String(bool);},'date':function(date){function format(number){return(number<10)?'0'+number:number;}
+return'"'+date.getFullYear()+'-'+
+format(date.getMonth()+1)+'-'+
+format(date.getDate())+'T'+
+format(date.getHours())+':'+
+format(date.getMinutes())+':'+
+format(date.getSeconds())+'"';}},CLASS_NAME:"OpenLayers.Format.JSON"});OpenLayers.Format.GeoJSON=OpenLayers.Class(OpenLayers.Format.JSON,{ignoreExtraDims:false,read:function(json,type,filter){type=(type)?type:"FeatureCollection";var results=null;var obj=null;if(typeof json=="string"){obj=OpenLayers.Format.JSON.prototype.read.apply(this,[json,filter]);}else{obj=json;}
+if(!obj){OpenLayers.Console.error("Bad JSON: "+json);}else if(typeof(obj.type)!="string"){OpenLayers.Console.error("Bad GeoJSON - no type: "+json);}else if(this.isValidType(obj,type)){switch(type){case"Geometry":try{results=this.parseGeometry(obj);}catch(err){OpenLayers.Console.error(err);}
+break;case"Feature":try{results=this.parseFeature(obj);results.type="Feature";}catch(err){OpenLayers.Console.error(err);}
+break;case"FeatureCollection":results=[];switch(obj.type){case"Feature":try{results.push(this.parseFeature(obj));}catch(err){results=null;OpenLayers.Console.error(err);}
+break;case"FeatureCollection":for(var i=0,len=obj.features.length;i<len;++i){try{results.push(this.parseFeature(obj.features[i]));}catch(err){results=null;OpenLayers.Console.error(err);}}
+break;default:try{var geom=this.parseGeometry(obj);results.push(new OpenLayers.Feature.Vector(geom));}catch(err){results=null;OpenLayers.Console.error(err);}}
+break;}}
+return results;},isValidType:function(obj,type){var valid=false;switch(type){case"Geometry":if(OpenLayers.Util.indexOf(["Point","MultiPoint","LineString","MultiLineString","Polygon","MultiPolygon","Box","GeometryCollection"],obj.type)==-1){OpenLayers.Console.error("Unsupported geometry type: "+
+obj.type);}else{valid=true;}
+break;case"FeatureCollection":valid=true;break;default:if(obj.type==type){valid=true;}else{OpenLayers.Console.error("Cannot convert types from "+
+obj.type+" to "+type);}}
+return valid;},parseFeature:function(obj){var feature,geometry,attributes,bbox;attributes=(obj.properties)?obj.properties:{};bbox=(obj.geometry&&obj.geometry.bbox)||obj.bbox;try{geometry=this.parseGeometry(obj.geometry);}catch(err){throw err;}
+feature=new OpenLayers.Feature.Vector(geometry,attributes);if(bbox){feature.bounds=OpenLayers.Bounds.fromArray(bbox);}
+if(obj.id){feature.fid=obj.id;}
+return feature;},parseGeometry:function(obj){if(obj==null){return null;}
+var geometry,collection=false;if(obj.type=="GeometryCollection"){if(!(OpenLayers.Util.isArray(obj.geometries))){throw"GeometryCollection must have geometries array: "+obj;}
+var numGeom=obj.geometries.length;var components=new Array(numGeom);for(var i=0;i<numGeom;++i){components[i]=this.parseGeometry.apply(this,[obj.geometries[i]]);}
+geometry=new OpenLayers.Geometry.Collection(components);collection=true;}else{if(!(OpenLayers.Util.isArray(obj.coordinates))){throw"Geometry must have coordinates array: "+obj;}
+if(!this.parseCoords[obj.type.toLowerCase()]){throw"Unsupported geometry type: "+obj.type;}
+try{geometry=this.parseCoords[obj.type.toLowerCase()].apply(this,[obj.coordinates]);}catch(err){throw err;}}
+if(this.internalProjection&&this.externalProjection&&!collection){geometry.transform(this.externalProjection,this.internalProjection);}
+return geometry;},parseCoords:{"point":function(array){if(this.ignoreExtraDims==false&&array.length!=2){throw"Only 2D points are supported: "+array;}
+return new OpenLayers.Geometry.Point(array[0],array[1]);},"multipoint":function(array){var points=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["point"].apply(this,[array[i]]);}catch(err){throw err;}
+points.push(p);}
+return new OpenLayers.Geometry.MultiPoint(points);},"linestring":function(array){var points=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["point"].apply(this,[array[i]]);}catch(err){throw err;}
+points.push(p);}
+return new OpenLayers.Geometry.LineString(points);},"multilinestring":function(array){var lines=[];var l=null;for(var i=0,len=array.length;i<len;++i){try{l=this.parseCoords["linestring"].apply(this,[array[i]]);}catch(err){throw err;}
+lines.push(l);}
+return new OpenLayers.Geometry.MultiLineString(lines);},"polygon":function(array){var rings=[];var r,l;for(var i=0,len=array.length;i<len;++i){try{l=this.parseCoords["linestring"].apply(this,[array[i]]);}catch(err){throw err;}
+r=new OpenLayers.Geometry.LinearRing(l.components);rings.push(r);}
+return new OpenLayers.Geometry.Polygon(rings);},"multipolygon":function(array){var polys=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["polygon"].apply(this,[array[i]]);}catch(err){throw err;}
+polys.push(p);}
+return new OpenLayers.Geometry.MultiPolygon(polys);},"box":function(array){if(array.length!=2){throw"GeoJSON box coordinates must have 2 elements";}
+return new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing([new OpenLayers.Geometry.Point(array[0][0],array[0][1]),new OpenLayers.Geometry.Point(array[1][0],array[0][1]),new OpenLayers.Geometry.Point(array[1][0],array[1][1]),new OpenLayers.Geometry.Point(array[0][0],array[1][1]),new OpenLayers.Geometry.Point(array[0][0],array[0][1])])]);}},write:function(obj,pretty){var geojson={"type":null};if(OpenLayers.Util.isArray(obj)){geojson.type="FeatureCollection";var numFeatures=obj.length;geojson.features=new Array(numFeatures);for(var i=0;i<numFeatures;++i){var element=obj[i];if(!element instanceof OpenLayers.Feature.Vector){var msg="FeatureCollection only supports collections "+"of features: "+element;throw msg;}
+geojson.features[i]=this.extract.feature.apply(this,[element]);}}else if(obj.CLASS_NAME.indexOf("OpenLayers.Geometry")==0){geojson=this.extract.geometry.apply(this,[obj]);}else if(obj instanceof OpenLayers.Feature.Vector){geojson=this.extract.feature.apply(this,[obj]);if(obj.layer&&obj.layer.projection){geojson.crs=this.createCRSObject(obj);}}
+return OpenLayers.Format.JSON.prototype.write.apply(this,[geojson,pretty]);},createCRSObject:function(object){var proj=object.layer.projection.toString();var crs={};if(proj.match(/epsg:/i)){var code=parseInt(proj.substring(proj.indexOf(":")+1));if(code==4326){crs={"type":"name","properties":{"name":"urn:ogc:def:crs:OGC:1.3:CRS84"}};}else{crs={"type":"name","properties":{"name":"EPSG:"+code}};}}
+return crs;},extract:{'feature':function(feature){var geom=this.extract.geometry.apply(this,[feature.geometry]);var json={"type":"Feature","properties":feature.attributes,"geometry":geom};if(feature.fid!=null){json.id=feature.fid;}
+return json;},'geometry':function(geometry){if(geometry==null){return null;}
+if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);}
+var geometryType=geometry.CLASS_NAME.split('.')[2];var data=this.extract[geometryType.toLowerCase()].apply(this,[geometry]);var json;if(geometryType=="Collection"){json={"type":"GeometryCollection","geometries":data};}else{json={"type":geometryType,"coordinates":data};}
+return json;},'point':function(point){return[point.x,point.y];},'multipoint':function(multipoint){var array=[];for(var i=0,len=multipoint.components.length;i<len;++i){array.push(this.extract.point.apply(this,[multipoint.components[i]]));}
+return array;},'linestring':function(linestring){var array=[];for(var i=0,len=linestring.components.length;i<len;++i){array.push(this.extract.point.apply(this,[linestring.components[i]]));}
+return array;},'multilinestring':function(multilinestring){var array=[];for(var i=0,len=multilinestring.components.length;i<len;++i){array.push(this.extract.linestring.apply(this,[multilinestring.components[i]]));}
+return array;},'polygon':function(polygon){var array=[];for(var i=0,len=polygon.components.length;i<len;++i){array.push(this.extract.linestring.apply(this,[polygon.components[i]]));}
+return array;},'multipolygon':function(multipolygon){var array=[];for(var i=0,len=multipolygon.components.length;i<len;++i){array.push(this.extract.polygon.apply(this,[multipolygon.components[i]]));}
+return array;},'collection':function(collection){var len=collection.components.length;var array=new Array(len);for(var i=0;i<len;++i){array[i]=this.extract.geometry.apply(this,[collection.components[i]]);}
+return array;}},CLASS_NAME:"OpenLayers.Format.GeoJSON"});OpenLayers.Lang["nn"]=OpenLayers.Util.applyDefaults({'Scale = 1 : ${scaleDenom}':"Skala = 1 : ${scaleDenom}"});OpenLayers.Lang["fi"]=OpenLayers.Util.applyDefaults({'Permalink':"Ikilinkki",'Overlays':"Kerrokset",'Base Layer':"Peruskerros",'W':"L",'E':"I",'N':"P",'S':"E"});OpenLayers.Lang["pl"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nieobsługiwane żądanie zwróciło ${statusText}",'Permalink':"Permalink",'Overlays':"Nakładki",'Base Layer':"Warstwa podstawowa",'noFID':"Nie można zaktualizować funkcji, dla których nie ma FID.",'browserNotSupported':"Twoja przeglądarka nie obsługuje renderowania wektorów. Obecnie obsługiwane renderowanie to:\n${renderers}",'minZoomLevelError':"Właściwość minZoomLevel jest przeznaczona tylko do użytku "+"z warstwami FixedZoomLevels-descendent."+"Warstwa wfs, która sprawdza minZoomLevel jest reliktem przeszłości."+"Nie możemy jej jednak usunąc bez mozliwości łamania OL aplikacji, "+"które mogą być od niej zależne. "+"Dlatego jesteśmy za deprecjację -- minZoomLevel "+"zostanie usunięta w wersji 3.0. W zamian prosze użyj "+"min/max rozdzielczości w sposób opisany tutaj: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transakcja WFS: SUKCES ${response}",'commitFailed':"Transakcja WFS: FAILED ${response}",'googleWarning':"Warstwa Google nie był w stanie załadować się poprawnie.<br><br>"+"Aby pozbyć się tej wiadomości, wybierz nową Warstwe podstawową "+"w przełączniku warstw w górnym prawym rogu mapy.<br><br>"+"Najprawdopodobniej jest to spowodowane tym, że biblioteka Google Maps "+"nie jest załadowana, lub nie zawiera poprawnego klucza do API dla twojej strony<br><br>"+"Programisto: Aby uzyskać pomoc , "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>kliknij tutaj</a>",'getLayerWarning':"Warstwa ${layerType} nie mogła zostać załadowana poprawnie.<br><br>"+"Aby pozbyć się tej wiadomości, wybierz nową Warstwe podstawową "+"w przełączniku warstw w górnym prawym rogu mapy.<br><br>"+"Najprawdopodobniej jest to spowodowane tym, że biblioteka ${layerLib} "+"nie jest załadowana, lub może(o ile biblioteka tego wymaga) "+"byc potrzebny klucza do API dla twojej strony<br><br>"+"Programisto: Aby uzyskać pomoc , "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>kliknij tutaj</a>",'Scale = 1 : ${scaleDenom}':"Skala = 1 : ${scaleDenom}",'W':'ZACH','E':'WSCH','N':'PN','S':'PD','Graticule':'Siatka','reprojectDeprecated':"w warstwie ${layerName} używasz opcji 'reproject'. "+"Ta opcja jest przestarzała: "+"jej zastosowanie został zaprojektowany, aby wspierać wyświetlania danych przez komercyjne mapy, "+"jednak obecnie ta funkcjonalność powinien zostać osiągnięty za pomocą Spherical Mercator "+"its use was designed to support displaying data over commercial. Więcje informacji na ten temat możesz znaleźć na stronie "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Ta metoda jest przestarzała i będzie usunięta od wersji 3.0. "+"W zamian użyj ${newMethod}.",'proxyNeeded':"Prawdopodobnie musisz ustawić OpenLayers.ProxyHost aby otrzymać dostęp do ${url}."+"See http://trac.osgeo.org/openlayers/wiki/FrequentlyAskedQuestions#ProxyHost"});OpenLayers.Lang.es={'unhandledRequest':"Respuesta a petición no gestionada ${statusText}",'Permalink':"Enlace permanente",'Overlays':"Capas superpuestas",'Base Layer':"Capa Base",'noFID':"No se puede actualizar un elemento para el que no existe FID.",'browserNotSupported':"Su navegador no soporta renderización vectorial. Los renderizadores soportados actualmente son:\n${renderers}",'minZoomLevelError':"La propiedad minZoomLevel debe sólo utilizarse "+"con las capas que tienen FixedZoomLevels. El hecho de que "+"una capa wfs compruebe minZoomLevel es una reliquia del "+"pasado. Sin embargo, no podemos eliminarla sin discontinuar "+"probablemente las aplicaciones OL que puedan depender de ello. "+"Así pues estamos haciéndolo obsoleto --la comprobación "+"minZoomLevel se eliminará en la versión 3.0. Utilice el ajuste "+"de resolution min/max en su lugar, tal como se describe aquí: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transacción WFS: ÉXITO ${response}",'commitFailed':"Transacción WFS: FALLÓ ${response}",'googleWarning':"La capa Google no pudo ser cargada correctamente.<br><br>"+"Para evitar este mensaje, seleccione una nueva Capa Base "+"en el selector de capas en la esquina superior derecha.<br><br>"+"Probablemente, esto se debe a que el script de la biblioteca de "+"Google Maps no fue correctamente incluido en su página, o no "+"contiene la clave del API correcta para su sitio.<br><br>"+"Desarrolladores: Para ayudar a hacer funcionar esto correctamente, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>haga clic aquí</a>",'getLayerWarning':"La capa ${layerType} no pudo ser cargada correctamente.<br><br>"+"Para evitar este mensaje, seleccione una nueva Capa Base "+"en el selector de capas en la esquina superior derecha.<br><br>"+"Probablemente, esto se debe a que el script de "+"la biblioteca ${layerLib} "+"no fue correctamente incluido en su página.<br><br>"+"Desarrolladores: Para ayudar a hacer funcionar esto correctamente, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>haga clic aquí</a>",'Scale = 1 : ${scaleDenom}':"Escala = 1 : ${scaleDenom}",'W':'O','E':'E','N':'N','S':'S','Graticule':'Retícula','reprojectDeprecated':"Está usando la opción 'reproject' en la capa "+"${layerName}. Esta opción es obsoleta: su uso fue diseñado "+"para soportar la visualización de datos sobre mapas base comerciales, "+"pero ahora esa funcionalidad debería conseguirse mediante el soporte "+"de la proyección Spherical Mercator. Más información disponible en "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Este método es obsoleto y se eliminará en la versión 3.0. "+"Por favor utilice el método ${newMethod} en su lugar.",'end':''};OpenLayers.Layer.SphericalMercator={getExtent:function(){var extent=null;if(this.sphericalMercator){extent=this.map.calculateBounds();}else{extent=OpenLayers.Layer.FixedZoomLevels.prototype.getExtent.apply(this);}
+return extent;},getLonLatFromViewPortPx:function(viewPortPx){return OpenLayers.Layer.prototype.getLonLatFromViewPortPx.apply(this,arguments);},getViewPortPxFromLonLat:function(lonlat){return OpenLayers.Layer.prototype.getViewPortPxFromLonLat.apply(this,arguments);},initMercatorParameters:function(){this.RESOLUTIONS=[];var maxResolution=156543.03390625;for(var zoom=0;zoom<=this.MAX_ZOOM_LEVEL;++zoom){this.RESOLUTIONS[zoom]=maxResolution/Math.pow(2,zoom);}
+this.units="m";this.projection=this.projection||"EPSG:900913";},forwardMercator:(function(){var gg=new OpenLayers.Projection("EPSG:4326");var sm=new OpenLayers.Projection("EPSG:900913");return function(lon,lat){var point=OpenLayers.Projection.transform({x:lon,y:lat},gg,sm);return new OpenLayers.LonLat(point.x,point.y);};})(),inverseMercator:(function(){var gg=new OpenLayers.Projection("EPSG:4326");var sm=new OpenLayers.Projection("EPSG:900913");return function(x,y){var point=OpenLayers.Projection.transform({x:x,y:y},sm,gg);return new OpenLayers.LonLat(point.x,point.y);};})()};OpenLayers.Lang["ru"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Необработанный запрос вернул ${statusText}",'Permalink':"Постоянная ссылка",'Overlays':"Слои",'Base Layer':"Основной слой",'noFID':"Невозможно обновить объект, для которого нет FID.",'browserNotSupported':"Ваш браузер не поддерживает векторную графику. На данный момент поддерживаются:\n${renderers}",'minZoomLevelError':"Свойство minZoomLevel предназначено только для использования со слоями, являющимися потомками FixedZoomLevels. То, что этот WFS-слой проверяется на minZoomLevel — реликт прошлого. Однако мы не можем удалить эту функцию, так как, возможно, от неё зависят некоторые основанные на OpenLayers приложения. Функция объявлена устаревшей — проверка minZoomLevel будет удалена в 3.0. Пожалуйста, используйте вместо неё настройку мин/макс разрешения, описанную здесь: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Транзакция WFS: УСПЕШНО ${response}",'commitFailed':"Транзакция WFS: ОШИБКА ${response}",'googleWarning':"Слой Google не удалось нормально загрузить.\x3cbr\x3e\x3cbr\x3eЧтобы избавиться от этого сообщения, выбите другой основной слой в переключателе в правом верхнем углу.\x3cbr\x3e\x3cbr\x3eСкорее всего, причина в том, что библиотека Google Maps не была включена или не содержит корректного API-ключа для вашего сайта.\x3cbr\x3e\x3cbr\x3eРазработчикам: чтобы узнать, как сделать, чтобы всё заработало, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eщёлкните тут\x3c/a\x3e",'getLayerWarning':"Слой ${layerType} не удалось нормально загрузить. \x3cbr\x3e\x3cbr\x3eЧтобы избавиться от этого сообщения, выбите другой основной слой в переключателе в правом верхнем углу.\x3cbr\x3e\x3cbr\x3eСкорее всего, причина в том, что библиотека ${layerLib} не была включена или была включена некорректно.\x3cbr\x3e\x3cbr\x3eРазработчикам: чтобы узнать, как сделать, чтобы всё заработало, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eщёлкните тут\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Масштаб = 1 : ${scaleDenom}",'W':"З",'E':"В",'N':"С",'S':"Ю",'reprojectDeprecated':"Вы используете опцию \'reproject\' для слоя ${layerName}. Эта опция является устаревшей: ее использование предполагалось для поддержки показа данных поверх коммерческих базовых карт, но теперь этот функционал несёт встроенная поддержка сферической проекции Меркатора. Больше сведений доступно на http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Этот метод считается устаревшим и будет удалён в версии 3.0. Пожалуйста, пользуйтесь ${newMethod}."});OpenLayers.Lang["hsb"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Wotmołwa njewobdźěłaneho naprašowanja ${statusText}",'Permalink':"Trajny wotkaz",'Overlays':"Naworštowanja",'Base Layer':"Zakładna runina",'noFID':"Funkcija, za kotruž FID njeje, njeda so aktualizować.",'browserNotSupported':"Twój wobhladowak wektorowe rysowanje njepodpěruje. Tuchwilu podpěrowane rysowaki su:\n${renderers}",'minZoomLevelError':"Kajkosć minZoomLevel je jenož za wužiwanje z worštami myslena, kotrež wot FixedZoomLevels pochadźeja. Zo tuta woršta wfs za minZoomLevel přepruwuje, je relikt zańdźenosće. Njemóžemy wšak ju wotstronić, bjeztoho zo aplikacije, kotrež na OpenLayers bazěruja a snano tutu kajkosć wužiwaja, hižo njefunguja. Tohodla smy ju jako zestarjenu woznamjenili -- přepruwowanje za minZoomLevel budu so we wersiji 3.0 wotstronjeć. Prošu wužij město toho nastajenje min/max, kaž je tu wopisane: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-Transakcija: WUSPĚŠNA ${response}",'commitFailed':"WFS-Transakcija: NJEPORADŹENA ${response}",'googleWarning':"Woršta Google njemóžeše so korektnje začitać.\x3cbr\x3e\x3cbr\x3eZo by tutu zdźělenku wotbył, wubjer nowy BaseLayer z wuběra worštow horjeka naprawo.\x3cbr\x3e\x3cbr\x3eNajskerje so to stawa, dokelž skript biblioteki Google Maps pak njebu zapřijaty pak njewobsahuje korektny kluč API za twoje sydło.\x3cbr\x3e\x3cbr\x3eWuwiwarjo: Za pomoc ke korektnemu fungowanju worštow\n\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3etu kliknyć\x3c/a\x3e",'getLayerWarning':"Woršta ${layerType} njemóžeše so korektnje začitać.\x3cbr\x3e\x3cbr\x3eZo by tutu zdźělenku wotbył, wubjer nowy BaseLayer z wuběra worštow horjeka naprawo.\x3cbr\x3e\x3cbr\x3eNajskerje so to stawa, dokelž skript biblioteki ${layerLib} njebu korektnje zapřijaty.\x3cbr\x3e\x3cbr\x3eWuwiwarjo: Za pomoc ke korektnemu fungowanju worštow\n\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3etu kliknyć\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Měritko = 1 : ${scaleDenom}",'W':"Z",'E':"W",'N':"S",'S':"J",'reprojectDeprecated':"Wužiwaš opciju \"reproject\" wořšty ${layerName}. Tuta opcija je zestarjena: jeje wužiwanje bě myslene, zo by zwobraznjenje datow nad komercielnymi bazowymi kartami podpěrało, ale funkcionalnosć měła so nětko z pomocu Sperical Mercator docpěć. Dalše informacije steja na http://trac.openlayers.org/wiki/SphericalMercator k dispoziciji.",'methodDeprecated':"Tuta metoda je so njeschwaliła a budźe so w 3.0 wotstronjeć. Prošu wužij ${newMethod} město toho."});OpenLayers.Lang["de"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Unbehandelte Anfragerückmeldung ${statusText}",'Permalink':"Permalink",'Overlays':"Overlays",'Base Layer':"Grundkarte",'noFID':"Ein Feature, für das keine FID existiert, kann nicht aktualisiert werden.",'browserNotSupported':"Ihr Browser unterstützt keine Vektordarstellung. Aktuell unterstützte Renderer:\n${renderers}",'minZoomLevelError':"Die \x3ccode\x3eminZoomLevel\x3c/code\x3e-Eigenschaft ist nur für die Verwendung mit \x3ccode\x3eFixedZoomLevels\x3c/code\x3e-untergeordneten Layers vorgesehen. Das dieser \x3ctt\x3ewfs\x3c/tt\x3e-Layer die \x3ccode\x3eminZoomLevel\x3c/code\x3e-Eigenschaft überprüft ist ein Relikt der Vergangenheit. Wir können diese Überprüfung nicht entfernen, ohne das OL basierende Applikationen nicht mehr funktionieren. Daher markieren wir es als veraltet - die \x3ccode\x3eminZoomLevel\x3c/code\x3e-Überprüfung wird in Version 3.0 entfernt werden. Bitte verwenden Sie stattdessen die Min-/Max-Lösung, wie sie unter http://trac.openlayers.org/wiki/SettingZoomLevels beschrieben ist.",'commitSuccess':"WFS-Transaktion: Erfolgreich ${response}",'commitFailed':"WFS-Transaktion: Fehlgeschlagen ${response}",'googleWarning':"Der Google-Layer konnte nicht korrekt geladen werden.\x3cbr\x3e\x3cbr\x3eUm diese Meldung nicht mehr zu erhalten, wählen Sie einen anderen Hintergrundlayer aus dem LayerSwitcher in der rechten oberen Ecke.\x3cbr\x3e\x3cbr\x3eSehr wahrscheinlich tritt dieser Fehler auf, weil das Skript der Google-Maps-Bibliothek nicht eingebunden wurde oder keinen gültigen API-Schlüssel für Ihre URL enthält.\x3cbr\x3e\x3cbr\x3eEntwickler: Besuche \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3edas Wiki\x3c/a\x3e für Hilfe zum korrekten Einbinden des Google-Layers",'getLayerWarning':"Der ${layerType}-Layer konnte nicht korrekt geladen werden.\x3cbr\x3e\x3cbr\x3eUm diese Meldung nicht mehr zu erhalten, wählen Sie einen anderen Hintergrundlayer aus dem LayerSwitcher in der rechten oberen Ecke.\x3cbr\x3e\x3cbr\x3eSehr wahrscheinlich tritt dieser Fehler auf, weil das Skript der \'${layerLib}\'-Bibliothek nicht eingebunden wurde.\x3cbr\x3e\x3cbr\x3eEntwickler: Besuche \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3edas Wiki\x3c/a\x3e für Hilfe zum korrekten Einbinden von Layern",'Scale = 1 : ${scaleDenom}':"Maßstab = 1 : ${scaleDenom}",'W':"W",'E':"O",'N':"N",'S':"S",'reprojectDeprecated':"Sie verwenden die „Reproject“-Option des Layers ${layerName}. Diese Option ist veraltet: Sie wurde entwickelt um die Anzeige von Daten auf kommerziellen Basiskarten zu unterstützen, aber diese Funktion sollte jetzt durch Unterstützung der „Spherical Mercator“ erreicht werden. Weitere Informationen sind unter http://trac.openlayers.org/wiki/SphericalMercator verfügbar.",'methodDeprecated':"Die Methode ist veraltet und wird in 3.0 entfernt. Bitte verwende stattdessen ${newMethod}."});OpenLayers.ProxyHost="";OpenLayers.Request={DEFAULT_CONFIG:{method:"GET",url:window.location.href,async:true,user:undefined,password:undefined,params:null,proxy:OpenLayers.ProxyHost,headers:{},data:null,callback:function(){},success:null,failure:null,scope:null},URL_SPLIT_REGEX:/([^:]*:)\/\/([^:]*:?[^@]*@)?([^:\/\?]*):?([^\/\?]*)/,events:new OpenLayers.Events(this),makeSameOrigin:function(url,proxy){var sameOrigin=url.indexOf("http")!==0;var urlParts=!sameOrigin&&url.match(this.URL_SPLIT_REGEX);if(urlParts){var location=window.location;sameOrigin=urlParts[1]==location.protocol&&urlParts[3]==location.hostname;var uPort=urlParts[4],lPort=location.port;if(uPort!=80&&uPort!=""||lPort!="80"&&lPort!=""){sameOrigin=sameOrigin&&uPort==lPort;}}
+if(!sameOrigin){if(proxy){if(typeof proxy=="function"){url=proxy(url);}else{url=proxy+encodeURIComponent(url);}}else{OpenLayers.Console.warn(OpenLayers.i18n("proxyNeeded"),{url:url});}}
+return url;},issue:function(config){var defaultConfig=OpenLayers.Util.extend(this.DEFAULT_CONFIG,{proxy:OpenLayers.ProxyHost});config=OpenLayers.Util.applyDefaults(config,defaultConfig);var customRequestedWithHeader=false,headerKey;for(headerKey in config.headers){if(config.headers.hasOwnProperty(headerKey)){if(headerKey.toLowerCase()==='x-requested-with'){customRequestedWithHeader=true;}}}
+if(customRequestedWithHeader===false){config.headers['X-Requested-With']='XMLHttpRequest';}
+var request=new OpenLayers.Request.XMLHttpRequest();var url=OpenLayers.Util.urlAppend(config.url,OpenLayers.Util.getParameterString(config.params||{}));url=OpenLayers.Request.makeSameOrigin(url,config.proxy);request.open(config.method,url,config.async,config.user,config.password);for(var header in config.headers){request.setRequestHeader(header,config.headers[header]);}
+var events=this.events;var self=this;request.onreadystatechange=function(){if(request.readyState==OpenLayers.Request.XMLHttpRequest.DONE){var proceed=events.triggerEvent("complete",{request:request,config:config,requestUrl:url});if(proceed!==false){self.runCallbacks({request:request,config:config,requestUrl:url});}}};if(config.async===false){request.send(config.data);}else{window.setTimeout(function(){if(request.readyState!==0){request.send(config.data);}},0);}
+return request;},runCallbacks:function(options){var request=options.request;var config=options.config;var complete=(config.scope)?OpenLayers.Function.bind(config.callback,config.scope):config.callback;var success;if(config.success){success=(config.scope)?OpenLayers.Function.bind(config.success,config.scope):config.success;}
+var failure;if(config.failure){failure=(config.scope)?OpenLayers.Function.bind(config.failure,config.scope):config.failure;}
+if(OpenLayers.Util.createUrlObject(config.url).protocol=="file:"&&request.responseText){request.status=200;}
+complete(request);if(!request.status||(request.status>=200&&request.status<300)){this.events.triggerEvent("success",options);if(success){success(request);}}
+if(request.status&&(request.status<200||request.status>=300)){this.events.triggerEvent("failure",options);if(failure){failure(request);}}},GET:function(config){config=OpenLayers.Util.extend(config,{method:"GET"});return OpenLayers.Request.issue(config);},POST:function(config){config=OpenLayers.Util.extend(config,{method:"POST"});config.headers=config.headers?config.headers:{};if(!("CONTENT-TYPE"in OpenLayers.Util.upperCaseObject(config.headers))){config.headers["Content-Type"]="application/xml";}
+return OpenLayers.Request.issue(config);},PUT:function(config){config=OpenLayers.Util.extend(config,{method:"PUT"});config.headers=config.headers?config.headers:{};if(!("CONTENT-TYPE"in OpenLayers.Util.upperCaseObject(config.headers))){config.headers["Content-Type"]="application/xml";}
+return OpenLayers.Request.issue(config);},DELETE:function(config){config=OpenLayers.Util.extend(config,{method:"DELETE"});return OpenLayers.Request.issue(config);},HEAD:function(config){config=OpenLayers.Util.extend(config,{method:"HEAD"});return OpenLayers.Request.issue(config);},OPTIONS:function(config){config=OpenLayers.Util.extend(config,{method:"OPTIONS"});return OpenLayers.Request.issue(config);}};OpenLayers.Lang['da-DK']={'unhandledRequest':"En ikke håndteret forespørgsel returnerede ${statusText}",'Permalink':"Permalink",'Overlays':"Kortlag",'Base Layer':"Baggrundslag",'noFID':"Kan ikke opdateret en feature (et objekt) der ikke har et FID.",'browserNotSupported':"Din browser understøtter ikke vektor visning. Følgende vektor visninger understøttes:\n${renderers}",'minZoomLevelError':"Egenskaben minZoomLevel er kun beregnet til brug "+"med FixedZoomLevels. At dette WFS lag kontrollerer "+"minZoomLevel egenskaben, er et levn fra en tidligere "+"version. Vi kan desværre ikke fjerne dette uden at risikere "+"at ødelægge eksisterende OL baserede programmer der "+" benytter denne funktionalitet. "+"Egenskaben bør derfor ikke anvendes, og minZoomLevel "+"kontrollen herunder vil blive fjernet i version 3.0. "+"Benyt istedet min/max opløsnings indstillingerne, som "+"er beskrevet her: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS transaktion: LYKKEDES ${response}",'commitFailed':"WFS transaktion: MISLYKKEDES ${response}",'googleWarning':"Google laget kunne ikke indlæses.<br><br>"+"For at fjerne denne besked, vælg et nyt bagrundskort i "+"lagskifteren i øverste højre hjørne.<br><br>"+"Fejlen skyldes formentlig at Google Maps bibliotekts "+"scriptet ikke er inkluderet, eller ikke indeholder den "+"korrkte API nøgle for dit site.<br><br>"+"Udviklere: For hjælp til at få dette til at fungere, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>klik her</a>",'getLayerWarning':"${layerType}-laget kunne ikke indlæses.<br><br>"+"For at fjerne denne besked, vælg et nyt bagrundskort i "+"lagskifteren i øverste højre hjørne.<br><br>"+"Fejlen skyldes formentlig at ${layerLib} bibliotekts "+"scriptet ikke er inkluderet.<br><br>"+"Udviklere: For hjælp til at få dette til at fungere, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>klik her</a>",'Scale = 1 : ${scaleDenom}':"Målforhold = 1 : ${scaleDenom}",'reprojectDeprecated':"Du anvender indstillingen 'reproject' på laget ${layerName}."+"Denne indstilling bør ikke længere anvendes. Den var beregnet "+"til at vise data ovenpå kommercielle grundkort, men den funktionalitet "+"bør nu opnås ved at anvende Spherical Mercator understøttelsen. "+"Mere information er tilgængelig her: "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Denne funktion bør ikke længere anvendes, og vil blive fjernet i version 3.0. "+"Anvend venligst funktionen ${newMethod} istedet."};OpenLayers.Lang["hu"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nem kezelt kérés visszatérése ${statusText}",'Permalink':"Permalink",'Overlays':"Rávetítések",'Base Layer':"Alapréteg",'noFID':"Nem frissíthető olyan jellemző, amely nem rendelkezik FID-del.",'browserNotSupported':"A böngészője nem támogatja a vektoros renderelést. A jelenleg támogatott renderelők:\n${renderers}",'minZoomLevelError':"A minZoomLevel tulajdonságot csak a következővel való használatra szánták: FixedZoomLevels-leszármazott fóliák. Ez azt jelenti, hogy a minZoomLevel wfs fólia jelölőnégyzetei már a múlté. Mi azonban nem távolíthatjuk el annak a veszélye nélkül, hogy az esetlegesen ettől függő OL alapú alkalmazásokat tönkretennénk. Ezért ezt érvénytelenítjük -- a minZoomLevel az alul levő jelölőnégyzet a 3.0-s verzióból el lesz távolítva. Kérjük, helyette használja a  min/max felbontás beállítást, amelyről az alábbi helyen talál leírást: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS tranzakció: SIKERES ${response}",'commitFailed':"WFS tranzakció: SIKERTELEN ${response}",'googleWarning':"A Google fólia betöltése sikertelen.\x3cbr\x3e\x3cbr\x3eAhhoz, hogy ez az üzenet eltűnjön, válasszon egy új BaseLayer fóliát a jobb felső sarokban található fóliakapcsoló segítségével.\x3cbr\x3e\x3cbr\x3eNagy valószínűséggel ez azért van, mert a Google Maps könyvtár parancsfájlja nem található, vagy nem tartalmazza az Ön oldalához tartozó megfelelő API-kulcsot.\x3cbr\x3e\x3cbr\x3eFejlesztőknek: A helyes működtetésre vonatkozó segítség az alábbi helyen érhető el, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3ekattintson ide\x3c/a\x3e",'getLayerWarning':"A(z) ${layerType} fólia nem töltődött be helyesen.\x3cbr\x3e\x3cbr\x3eAhhoz, hogy ez az üzenet eltűnjön, válasszon egy új BaseLayer fóliát a jobb felső sarokban található fóliakapcsoló segítségével.\x3cbr\x3e\x3cbr\x3eNagy valószínűséggel ez azért van, mert a(z) ${layerLib} könyvtár parancsfájlja helytelen.\x3cbr\x3e\x3cbr\x3eFejlesztőknek: A helyes működtetésre vonatkozó segítség az alábbi helyen érhető el, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3ekattintson ide\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Lépték = 1 : ${scaleDenom}",'W':"Ny",'E':"K",'N':"É",'S':"D",'reprojectDeprecated':"Ön a \'reproject\' beállítást használja a(z) ${layerName} fólián. Ez a beállítás érvénytelen: használata az üzleti alaptérképek fölötti adatok megjelenítésének támogatására szolgált, de ezt a funkció ezentúl a Gömbi Mercator használatával érhető el. További információ az alábbi helyen érhető el: http://trac.openlayers.org/wiki/SphericalMercator",'methodDeprecated':"Ez a módszer érvénytelenítve lett és a 3.0-s verzióból el lesz távolítva. Használja a(z) ${newMethod} módszert helyette."});OpenLayers.Lang["zh-TW"]={'unhandledRequest':"未處理的請求,傳回值為 ${statusText}。",'Permalink':"永久連結",'Overlays':"額外圖層",'Base Layer':"基礎圖層",'noFID':"因為沒有 FID 所以無法更新 feature。",'browserNotSupported':"您的瀏覽器未支援向量渲染. 目前支援的渲染方式是:\n${renderers}",'minZoomLevelError':"minZoomLevel 屬性僅適合用在 "+"FixedZoomLevels-descendent 類型的圖層. 這個"+"wfs layer 的 minZoomLevel 是過去所遺留下來的,"+"然而我們不能移除它而不讓它將"+"過去的程式相容性給破壞掉。"+"因此我們將會迴避使用它 -- minZoomLevel "+"會在3.0被移除,請改"+"用在這邊描述的 min/max resolution 設定: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaction: 成功 ${response}",'commitFailed':"WFS Transaction: 失敗 ${response}",'googleWarning':"The Google Layer 圖層無法被正確的載入。<br><br>"+"要迴避這個訊息, 請在右上角的圖層改變器裡,"+"選一個新的基礎圖層。<br><br>"+"很有可能是因為 Google Maps 的函式庫"+"腳本沒有被正確的置入,或沒有包含 "+"您網站上正確的 API key <br><br>"+"開發者: 要幫助這個行為正確完成,"+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>請按這裡</a>",'getLayerWarning':"${layerType} 圖層無法被正確的載入。<br><br>"+"要迴避這個訊息, 請在右上角的圖層改變器裡,"+"選一個新的基礎圖層。<br><br>"+"很有可能是因為 ${layerLib} 的函式庫"+"腳本沒有被正確的置入。<br><br>"+"開發者: 要幫助這個行為正確完成,"+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>請按這裡</a>",'Scale = 1 : ${scaleDenom}':"Scale = 1 : ${scaleDenom}",'reprojectDeprecated':"你正使用 'reproject' 這個選項 "+"在 ${layerName} 層。這個選項已經不再使用:"+"它的使用原本是設計用來支援在商業地圖上秀出資料,"+"但這個功能已經被"+"Spherical Mercator所取代。更多的資訊可以在 "+"http://trac.openlayers.org/wiki/SphericalMercator 找到。",'methodDeprecated':"這個方法已經不再使用且在3.0將會被移除,"+"請使用 ${newMethod} 來代替。",'end':''};OpenLayers.Control.DrawFeature=OpenLayers.Class(OpenLayers.Control,{layer:null,callbacks:null,multi:false,featureAdded:function(){},handlerOptions:null,initialize:function(layer,handler,options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.callbacks=OpenLayers.Util.extend({done:this.drawFeature,modify:function(vertex,feature){this.layer.events.triggerEvent("sketchmodified",{vertex:vertex,feature:feature});},create:function(vertex,feature){this.layer.events.triggerEvent("sketchstarted",{vertex:vertex,feature:feature});}},this.callbacks);this.layer=layer;this.handlerOptions=this.handlerOptions||{};this.handlerOptions.layerOptions=OpenLayers.Util.applyDefaults(this.handlerOptions.layerOptions,{renderers:layer.renderers,rendererOptions:layer.rendererOptions});if(!("multi"in this.handlerOptions)){this.handlerOptions.multi=this.multi;}
+var sketchStyle=this.layer.styleMap&&this.layer.styleMap.styles.temporary;if(sketchStyle){this.handlerOptions.layerOptions=OpenLayers.Util.applyDefaults(this.handlerOptions.layerOptions,{styleMap:new OpenLayers.StyleMap({"default":sketchStyle})});}
+this.handler=new handler(this,this.callbacks,this.handlerOptions);},drawFeature:function(geometry){var feature=new OpenLayers.Feature.Vector(geometry);var proceed=this.layer.events.triggerEvent("sketchcomplete",{feature:feature});if(proceed!==false){feature.state=OpenLayers.State.INSERT;this.layer.addFeatures([feature]);this.featureAdded(feature);this.events.triggerEvent("featureadded",{feature:feature});}},insertXY:function(x,y){if(this.handler&&this.handler.line){this.handler.insertXY(x,y);}},insertDeltaXY:function(dx,dy){if(this.handler&&this.handler.line){this.handler.insertDeltaXY(dx,dy);}},insertDirectionLength:function(direction,length){if(this.handler&&this.handler.line){this.handler.insertDirectionLength(direction,length);}},insertDeflectionLength:function(deflection,length){if(this.handler&&this.handler.line){this.handler.insertDeflectionLength(deflection,length);}},undo:function(){return this.handler.undo&&this.handler.undo();},redo:function(){return this.handler.redo&&this.handler.redo();},finishSketch:function(){this.handler.finishGeometry();},cancel:function(){this.handler.cancel();},CLASS_NAME:"OpenLayers.Control.DrawFeature"});OpenLayers.Lang["pt-br"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"A requisição retornou um erro não tratado: ${statusText}",'Permalink':"Link para essa página",'Overlays':"Camadas de Sobreposição",'Base Layer':"Camada Base",'noFID':"Não é possível atualizar uma feição que não tenha um FID.",'browserNotSupported':"Seu navegador não suporta renderização de vetores. Os renderizadores suportados atualmente são:\n${renderers}",'minZoomLevelError':"A propriedade minZoomLevel é de uso restrito das camadas descendentes de FixedZoomLevels. A verificação dessa propriedade pelas camadas wfs é um resíduo do passado. Não podemos, entretanto não é possível removê-la sem possívelmente quebrar o funcionamento de aplicações OL que possuem depência com ela. Portanto estamos tornando seu uso obsoleto -- a verificação desse atributo será removida na versão 3.0. Ao invés, use as opções de resolução min/max como descrito em: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transação WFS : SUCESSO ${response}",'commitFailed':"Transação WFS : ERRO ${response}",'googleWarning':"Não foi possível carregar a camada Google corretamente.\x3cbr\x3e\x3cbr\x3ePara se livrar dessa mensagem, selecione uma nova Camada Base, na ferramenta de alternação de camadas localização do canto superior direito.\x3cbr\x3e\x3cbr\x3eMuito provavelmente, isso foi causado porque o script da biblioteca do Google Maps não foi incluído, ou porque ele não contém a chave correta da API para o seu site.\x3cbr\x3e\x3cbr\x3eDesenvolvedores: Para obter ajuda em solucionar esse problema \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3ecliquem aqui\x3c/a\x3e",'getLayerWarning':"Não foi possível carregar a camada ${layerType} corretamente.\x3cbr\x3e\x3cbr\x3ePara se livrar dessa mensagem, selecione uma nova Camada Base, na ferramenta de alternação de camadas localização do canto superior direito.\x3cbr\x3e\x3cbr\x3eMuito provavelmente, isso foi causado porque o script da biblioteca ${layerLib} não foi incluído corretamente.\x3cbr\x3e\x3cbr\x3eDesenvolvedores: Para obter ajuda em solucionar esse problema \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3ecliquem aqui\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Escala = 1 : ${scaleDenom}",'W':"O",'E':"L",'N':"N",'S':"S",'reprojectDeprecated':"Você está usando a opção \'reproject\' na camada ${layerName}. Essa opção está obsoleta: seu uso foi projetado para suportar a visualização de dados sobre bases de mapas comerciais, entretanto essa funcionalidade deve agora ser alcançada usando o suporte à projeção Mercator. Mais informação está disponível em: http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Esse método está obsoleto e será removido na versão 3.0. Ao invés, por favor use ${newMethod}."});OpenLayers.Lang["zh-CN"]={'unhandledRequest':"未处理的请求,返回值为 ${statusText}",'Permalink':"永久链接",'Overlays':"叠加层",'Base Layer':"基础图层",'noFID':"无法更新feature,缺少FID。",'browserNotSupported':"你使用的浏览器不支持矢量渲染。当前支持的渲染方式包括:\n${renderers}",'minZoomLevelError':"minZoomLevel属性仅适合用于"+"使用了固定缩放级别的图层。这个 "+"wfs 图层检查 minZoomLevel 是过去遗留下来的。"+"然而,我们不能移除它,"+"而破坏依赖于它的基于OL的应用程序。"+"因此,我们废除了它 -- minZoomLevel "+"将会在3.0中被移除。请改用 "+"min/max resolution 设置,参考:"+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaction: 成功。 ${response}",'commitFailed':"WFS Transaction: 失败。 ${response}",'googleWarning':"Google图层不能正确加载。<br><br>"+"要消除这个信息,请在右上角的"+"图层控制面板中选择其他的基础图层。<br><br>"+"这种情况很可能是没有正确的包含Google地图脚本库,"+"或者是没有包含在你的站点上"+"使用的正确的Google Maps API密匙。<br><br>"+"开发者:获取使其正确工作的帮助信息,"+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>点击这里</a>",'getLayerWarning':"${layerType} 图层不能正确加载。<br><br>"+"要消除这个信息,请在右上角的"+"图层控制面板中选择其他的基础图层。<br><br>"+"这种情况很可能是没有正确的包含"+"${layerLib} 脚本库。<br><br>"+"开发者:获取使其正确工作的帮助信息,"+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>点击这里</a>",'Scale = 1 : ${scaleDenom}':"比例尺 = 1 : ${scaleDenom}",'reprojectDeprecated':"你正在使用 ${layerName} 图层上的'reproject'选项。"+"这个选项已经不再使用:"+"它是被设计用来支持显示商业的地图数据,"+"不过现在该功能可以通过使用Spherical Mercator来实现。"+"更多信息可以参阅"+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"该方法已经不再被支持,并且将在3.0中被移除。"+"请使用 ${newMethod} 方法来替代。",'end':''};OpenLayers.Lang["pt"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Servidor devolveu erro não contemplado ${statusText}",'Permalink':"Ligação permanente",'Overlays':"Sobreposições",'Base Layer':"Camada Base",'noFID':"Não é possível atualizar um elemento para a qual não há FID.",'browserNotSupported':"O seu navegador não suporta renderização vetorial. Actualmente os renderizadores suportados são:\n${renderers}",'minZoomLevelError':"A propriedade minZoomLevel só deve ser usada com as camadas descendentes da FixedZoomLevels. A verificação da propriedade por esta camada wfs é uma relíquia do passado. No entanto, não podemos removê-la sem correr o risco de afectar aplicações OL que dependam dela. Portanto, estamos a torná-la obsoleta -- a verificação minZoomLevel será removida na versão 3.0. Em vez dela, por favor, use as opções de resolução min/max descritas aqui: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transacção WFS: SUCESSO ${response}",'commitFailed':"Transacção WFS: FALHOU ${response}",'googleWarning':"A Camada Google não foi correctamente carregada.\x3cbr\x3e\x3cbr\x3ePara deixar de receber esta mensagem, seleccione uma nova Camada-Base no \'\'switcher\'\' de camadas no canto superior direito.\x3cbr\x3e\x3cbr\x3eProvavelmente, isto acontece porque o \'\'script\'\' da biblioteca do Google Maps não foi incluído ou não contém a chave API correcta para o seu sítio.\x3cbr\x3e\x3cbr\x3eProgramadores: Para ajuda sobre como solucionar o problema \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclique aqui\x3c/a\x3e .",'getLayerWarning':"A camada ${layerType} não foi correctamente carregada.\x3cbr\x3e\x3cbr\x3ePara desactivar esta mensagem, seleccione uma nova Camada-Base no \'\'switcher\'\' de camadas no canto superior direito.\x3cbr\x3e\x3cbr\x3eProvavelmente, isto acontece porque o \'\'script\'\' da biblioteca ${layerLib} não foi incluído correctamente.\x3cbr\x3e\x3cbr\x3eProgramadores: Para ajuda sobre como solucionar o problema \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclique aqui\x3c/a\x3e .",'Scale = 1 : ${scaleDenom}':"Escala = 1 : ${scaleDenom}",'W':"O",'E':"E",'N':"N",'S':"S",'reprojectDeprecated':"Está usando a opção \'reproject\' na camada ${layerName}. Esta opção é obsoleta: foi concebida para permitir a apresentação de dados sobre mapas-base comerciais, mas esta funcionalidade é agora suportada pelo Mercator Esférico. Mais informação está disponível em http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Este método foi declarado obsoleto e será removido na versão 3.0. Por favor, use ${newMethod} em vez disso."});OpenLayers.Rule=OpenLayers.Class({id:null,name:null,title:null,description:null,context:null,filter:null,elseFilter:false,symbolizer:null,symbolizers:null,minScaleDenominator:null,maxScaleDenominator:null,initialize:function(options){this.symbolizer={};OpenLayers.Util.extend(this,options);if(this.symbolizers){delete this.symbolizer;}
+this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){for(var i in this.symbolizer){this.symbolizer[i]=null;}
+this.symbolizer=null;delete this.symbolizers;},evaluate:function(feature){var context=this.getContext(feature);var applies=true;if(this.minScaleDenominator||this.maxScaleDenominator){var scale=feature.layer.map.getScale();}
+if(this.minScaleDenominator){applies=scale>=OpenLayers.Style.createLiteral(this.minScaleDenominator,context);}
+if(applies&&this.maxScaleDenominator){applies=scale<OpenLayers.Style.createLiteral(this.maxScaleDenominator,context);}
+if(applies&&this.filter){if(this.filter.CLASS_NAME=="OpenLayers.Filter.FeatureId"){applies=this.filter.evaluate(feature);}else{applies=this.filter.evaluate(context);}}
+return applies;},getContext:function(feature){var context=this.context;if(!context){context=feature.attributes||feature.data;}
+if(typeof this.context=="function"){context=this.context(feature);}
+return context;},clone:function(){var options=OpenLayers.Util.extend({},this);if(this.symbolizers){var len=this.symbolizers.length;options.symbolizers=new Array(len);for(var i=0;i<len;++i){options.symbolizers[i]=this.symbolizers[i].clone();}}else{options.symbolizer={};var value,type;for(var key in this.symbolizer){value=this.symbolizer[key];type=typeof value;if(type==="object"){options.symbolizer[key]=OpenLayers.Util.extend({},value);}else if(type==="string"){options.symbolizer[key]=value;}}}
+options.filter=this.filter&&this.filter.clone();options.context=this.context&&OpenLayers.Util.extend({},this.context);return new OpenLayers.Rule(options);},CLASS_NAME:"OpenLayers.Rule"});OpenLayers.Lang["gl"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Solicitude non xerada; a resposta foi: ${statusText}",'Permalink':"Ligazón permanente",'Overlays':"Capas superpostas",'Base Layer':"Capa base",'noFID':"Non se pode actualizar a funcionalidade para a que non hai FID.",'browserNotSupported':"O seu navegador non soporta a renderización de vectores. Os renderizadores soportados actualmente son:\n${renderers}",'minZoomLevelError':"A propiedade minZoomLevel é só para uso conxuntamente coas capas FixedZoomLevels-descendent. O feito de que esa capa wfs verifique o minZoomLevel é unha reliquia do pasado. Non podemos, con todo, eliminala sen a posibilidade de non romper as aplicacións baseadas en OL que poidan depender dela. Por iso a estamos deixando obsoleta (a comprobación minZoomLevel de embaixo será eliminada na versión 3.0). Por favor, no canto diso use o axuste de resolución mín/máx tal e como está descrito aquí: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transacción WFS: ÉXITO ${response}",'commitFailed':"Transacción WFS: FALLIDA ${response}",'googleWarning':"A capa do Google non puido cargarse correctamente.\x3cbr\x3e\x3cbr\x3ePara evitar esta mensaxe, escolla unha nova capa base no seleccionador de capas na marxe superior dereita.\x3cbr\x3e\x3cbr\x3eProbablemente, isto acontece porque a escritura da libraría do Google Maps ou ben non foi incluída ou ben non contén a clave API correcta para o seu sitio.\x3cbr\x3e\x3cbr\x3eDesenvolvedores: para axudar a facer funcionar isto correctamente, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3epremede aquí\x3c/a\x3e",'getLayerWarning':"A capa ${layerType} foi incapaz de cargarse correctamente.\x3cbr\x3e\x3cbr\x3ePara evitar esta mensaxe, escolla unha nova capa base no seleccionador de capas na marxe superior dereita.\x3cbr\x3e\x3cbr\x3eProbablemente, isto acontece porque a escritura da libraría ${layerLib} non foi ben incluída.\x3cbr\x3e\x3cbr\x3eDesenvolvedores: para axudar a facer funcionar isto correctamente, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3epremede aquí\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Escala = 1 : ${scaleDenom}",'W':"O",'E':"L",'N':"N",'S':"S",'reprojectDeprecated':"Está usando a opción \"reproject\" na capa ${layerName}. Esta opción está obsoleta: o seu uso foi deseñado para a visualización de datos sobre mapas base comerciais, pero esta funcionalidade debera agora ser obtida utilizando a proxección Spherical Mercator. Hai dispoñible máis información en http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Este método está obsoleto e será eliminado na versión 3.0. Por favor, no canto deste use ${newMethod}."});OpenLayers.Lang["ar"]=OpenLayers.Util.applyDefaults({'Permalink':"وصلة دائمة",'Base Layer':"الطبقة الاساسية",'Scale = 1 : ${scaleDenom}':"النسبة = 1 : ${scaleDenom}",'W':"غ",'E':"شر",'N':"شم",'S':"ج"});OpenLayers.Handler.Pinch=OpenLayers.Class(OpenLayers.Handler,{started:false,stopDown:false,pinching:false,last:null,start:null,touchstart:function(evt){var propagate=true;this.pinching=false;if(OpenLayers.Event.isMultiTouch(evt)){this.started=true;this.last=this.start={distance:this.getDistance(evt.touches),delta:0,scale:1};this.callback("start",[evt,this.start]);propagate=!this.stopDown;}else{this.started=false;this.start=null;this.last=null;}
+OpenLayers.Event.stop(evt);return propagate;},touchmove:function(evt){if(this.started&&OpenLayers.Event.isMultiTouch(evt)){this.pinching=true;var current=this.getPinchData(evt);this.callback("move",[evt,current]);this.last=current;OpenLayers.Event.stop(evt);}
+return true;},touchend:function(evt){if(this.started){this.started=false;this.pinching=false;this.callback("done",[evt,this.start,this.last]);this.start=null;this.last=null;}
+return true;},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.pinching=false;activated=true;}
+return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.started=false;this.pinching=false;this.start=null;this.last=null;deactivated=true;}
+return deactivated;},getDistance:function(touches){var t0=touches[0];var t1=touches[1];return Math.sqrt(Math.pow(t0.clientX-t1.clientX,2)+
+Math.pow(t0.clientY-t1.clientY,2));},getPinchData:function(evt){var distance=this.getDistance(evt.touches);var scale=distance/this.start.distance;return{distance:distance,delta:this.last.distance-distance,scale:scale};},CLASS_NAME:"OpenLayers.Handler.Pinch"});OpenLayers.Lang['lt']=OpenLayers.Util.applyDefaults({'unhandledRequest':"Neapdorota užklausa gražino ${statusText}",'Permalink':"Pastovi nuoroda",'Overlays':"Papildomi sluoksniai",'Base Layer':"Pagrindinis sluoksnis",'noFID':"Negaliu atnaujinti objekto, kuris neturi FID.",'browserNotSupported':"Jūsų naršyklė nemoka parodyti vektorių. Šiuo metu galima naudotis tokiais rodymo varikliais:\n{renderers}",'commitSuccess':"WFS Tranzakcija: PAVYKO ${response}",'commitFailed':"WFS Tranzakcija: ŽLUGO ${response}",'Scale = 1 : ${scaleDenom}':"Mastelis = 1 : ${scaleDenom}",'W':'V','E':'R','N':'Š','S':'P','Graticule':'Tinklelis','methodDeprecated':"Šis metodas yra pasenęs ir 3.0 versijoje bus pašalintas. "+"Prašome naudoti ${newMethod}.",'end':''});OpenLayers.Lang.ca={'unhandledRequest':"Resposta a petició no gestionada ${statusText}",'Permalink':"Enllaç permanent",'Overlays':"Capes addicionals",'Base Layer':"Capa Base",'noFID':"No es pot actualitzar un element per al que no existeix FID.",'browserNotSupported':"El seu navegador no suporta renderització vectorial. Els renderitzadors suportats actualment són:\n${renderers}",'minZoomLevelError':"La propietat minZoomLevel s'ha d'utilitzar només "+"amb les capes que tenen FixedZoomLevels. El fet que "+"una capa wfs comprovi minZoomLevel és una relíquia del "+"passat. No podem, però, eliminar-la sense trencar "+"les aplicacions d'OpenLayers que en puguin dependre. "+"Així doncs estem fent-la obsoleta -- la comprovació "+"minZoomLevel s'eliminarà a la versió 3.0. Feu servir "+"els paràmetres min/max resolution en substitució, tal com es descriu aquí: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transacció WFS: CORRECTA ${response}",'commitFailed':"Transacció WFS: HA FALLAT ${response}",'googleWarning':"La capa Google no s'ha pogut carregar correctament.<br><br>"+"Per evitar aquest missatge, seleccioneu una nova Capa Base "+"al gestor de capes de la cantonada superior dreta.<br><br>"+"Probablement això és degut a que l'script de la biblioteca de "+"Google Maps no ha estat inclòs a la vostra pàgina, o no "+"conté la clau de l'API correcta per a la vostra adreça.<br><br>"+"Desenvolupadors: Per obtenir consells sobre com fer anar això, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>féu clic aquí</a>",'getLayerWarning':"Per evitar aquest missatge, seleccioneu una nova Capa Base "+"al gestor de capes de la cantonada superior dreta.<br><br>"+"Probablement això és degut a que l'script de la biblioteca "+"${layerLib} "+"no ha estat inclòs a la vostra pàgina.<br><br>"+"Desenvolupadors: Per obtenir consells sobre com fer anar això, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>féu clic aquí</a>",'Scale = 1 : ${scaleDenom}':"Escala = 1 : ${scaleDenom}",'W':'O','E':'E','N':'N','S':'S','Graticule':'Retícula','reprojectDeprecated':"Esteu fent servir l'opció 'reproject' a la capa "+"${layerName}. Aquesta opció és obsoleta: el seu ús fou concebut "+"per suportar la visualització de dades sobre mapes base comercials, "+"però ara aquesta funcionalitat s'hauria d'assolir mitjançant el suport "+"de la projecció Spherical Mercator. Més informació disponible a "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Aquest mètode és obsolet i s'eliminarà a la versió 3.0. "+"Si us plau feu servir em mètode alternatiu ${newMethod}.",'end':''};OpenLayers.Lang["id"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Permintaan yang tak tertangani menghasilkan ${statusText}",'Permalink':"Pranala permanen",'Overlays':"Hamparan",'Base Layer':"Lapisan Dasar",'noFID':"Tidak dapat memperbarui fitur yang tidak memiliki FID.",'browserNotSupported':"Peramban Anda tidak mendukung penggambaran vektor. Penggambar yang didukung saat ini adalah:\n${renderers}",'minZoomLevelError':"Properti minZoomLevel hanya ditujukan bekerja dengan lapisan FixedZoomLevels-descendent. Pengecekan minZoomLevel oleh lapisan wfs adalah peninggalan masa lalu. Kami tidak dapat menghapusnya tanpa kemungkinan merusak aplikasi berbasis OL yang mungkin bergantung padanya. Karenanya, kami menganggapnya tidak berlaku -- Cek minZoomLevel di bawah ini akan dihapus pada 3.0. Silakan gunakan penyetelan resolusi min/maks seperti dijabarkan di sini: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaksi: BERHASIL ${respon}",'commitFailed':"WFS Transaksi: GAGAL ${respon}",'googleWarning':"Lapisan Google tidak dapat dimuat dengan benar.\x3cbr\x3e\x3cbr\x3eUntuk menghilangkan pesan ini, pilih suatu BaseLayer baru melalui penukar lapisan (layer switcher) di ujung kanan atas.\x3cbr\x3e\x3cbr\x3eKemungkinan besar ini karena pustaka skrip Google Maps tidak disertakan atau tidak mengandung kunci API yang tepat untuk situs Anda.\x3cbr\x3e\x3cbr\x3ePengembang: Untuk bantuan mengatasi masalah ini, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eklik di sini\x3c/a\x3e",'getLayerWarning':"Lapisan ${layerType} tidak dapat dimuat dengan benar.\x3cbr\x3e\x3cbr\x3eUntuk menghilangkan pesan ini, pilih suatu BaseLayer baru melalui penukar lapisan (layer switcher) di ujung kanan atas.\x3cbr\x3e\x3cbr\x3eKemungkinan besar ini karena pustaka skrip Google Maps tidak disertakan dengan benar.\x3cbr\x3e\x3cbr\x3ePengembang: Untuk bantuan mengatasi masalah ini, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eklik di sini\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Sekala = 1 : ${scaleDenom}",'W':"B",'E':"T",'N':"U",'S':"S",'reprojectDeprecated':"Anda menggunakan opsi \'reproject\' pada lapisan ${layerName}. Opsi ini telah ditinggalkan: penggunaannya dirancang untuk mendukung tampilan data melalui peta dasar komersial, tapi fungsionalitas tersebut saat ini harus dilakukan dengan menggunakan dukungan Spherical Mercator. Informasi lebih lanjut tersedia di http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Metode ini telah usang dan akan dihapus di 3.0. Sebaliknya, harap gunakan ${newMethod}."});OpenLayers.Filter.Comparison=OpenLayers.Class(OpenLayers.Filter,{type:null,property:null,value:null,matchCase:true,lowerBoundary:null,upperBoundary:null,initialize:function(options){OpenLayers.Filter.prototype.initialize.apply(this,[options]);if(this.type===OpenLayers.Filter.Comparison.LIKE&&options.matchCase===undefined){this.matchCase=null;}},evaluate:function(context){if(context instanceof OpenLayers.Feature.Vector){context=context.attributes;}
+var result=false;var got=context[this.property];var exp;switch(this.type){case OpenLayers.Filter.Comparison.EQUAL_TO:exp=this.value;if(!this.matchCase&&typeof got=="string"&&typeof exp=="string"){result=(got.toUpperCase()==exp.toUpperCase());}else{result=(got==exp);}
+break;case OpenLayers.Filter.Comparison.NOT_EQUAL_TO:exp=this.value;if(!this.matchCase&&typeof got=="string"&&typeof exp=="string"){result=(got.toUpperCase()!=exp.toUpperCase());}else{result=(got!=exp);}
+break;case OpenLayers.Filter.Comparison.LESS_THAN:result=got<this.value;break;case OpenLayers.Filter.Comparison.GREATER_THAN:result=got>this.value;break;case OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO:result=got<=this.value;break;case OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO:result=got>=this.value;break;case OpenLayers.Filter.Comparison.BETWEEN:result=(got>=this.lowerBoundary)&&(got<=this.upperBoundary);break;case OpenLayers.Filter.Comparison.LIKE:var regexp=new RegExp(this.value,"gi");result=regexp.test(got);break;}
+return result;},value2regex:function(wildCard,singleChar,escapeChar){if(wildCard=="."){throw new Error("'.' is an unsupported wildCard character for "+"OpenLayers.Filter.Comparison");}
+wildCard=wildCard?wildCard:"*";singleChar=singleChar?singleChar:".";escapeChar=escapeChar?escapeChar:"!";this.value=this.value.replace(new RegExp("\\"+escapeChar+"(.|$)","g"),"\\$1");this.value=this.value.replace(new RegExp("\\"+singleChar,"g"),".");this.value=this.value.replace(new RegExp("\\"+wildCard,"g"),".*");this.value=this.value.replace(new RegExp("\\\\.\\*","g"),"\\"+wildCard);this.value=this.value.replace(new RegExp("\\\\\\.","g"),"\\"+singleChar);return this.value;},regex2value:function(){var value=this.value;value=value.replace(/!/g,"!!");value=value.replace(/(\\)?\\\./g,function($0,$1){return $1?$0:"!.";});value=value.replace(/(\\)?\\\*/g,function($0,$1){return $1?$0:"!*";});value=value.replace(/\\\\/g,"\\");value=value.replace(/\.\*/g,"*");return value;},clone:function(){return OpenLayers.Util.extend(new OpenLayers.Filter.Comparison(),this);},CLASS_NAME:"OpenLayers.Filter.Comparison"});OpenLayers.Filter.Comparison.EQUAL_TO="==";OpenLayers.Filter.Comparison.NOT_EQUAL_TO="!=";OpenLayers.Filter.Comparison.LESS_THAN="<";OpenLayers.Filter.Comparison.GREATER_THAN=">";OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO="<=";OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO=">=";OpenLayers.Filter.Comparison.BETWEEN="..";OpenLayers.Filter.Comparison.LIKE="~";OpenLayers.Format.QueryStringFilter=(function(){var cmpToStr={};cmpToStr[OpenLayers.Filter.Comparison.EQUAL_TO]="eq";cmpToStr[OpenLayers.Filter.Comparison.NOT_EQUAL_TO]="ne";cmpToStr[OpenLayers.Filter.Comparison.LESS_THAN]="lt";cmpToStr[OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO]="lte";cmpToStr[OpenLayers.Filter.Comparison.GREATER_THAN]="gt";cmpToStr[OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO]="gte";cmpToStr[OpenLayers.Filter.Comparison.LIKE]="ilike";function regex2value(value){value=value.replace(/%/g,"\\%");value=value.replace(/\\\\\.(\*)?/g,function($0,$1){return $1?$0:"\\\\_";});value=value.replace(/\\\\\.\*/g,"\\\\%");value=value.replace(/(\\)?\.(\*)?/g,function($0,$1,$2){return $1||$2?$0:"_";});value=value.replace(/(\\)?\.\*/g,function($0,$1){return $1?$0:"%";});value=value.replace(/\\\./g,".");value=value.replace(/(\\)?\\\*/g,function($0,$1){return $1?$0:"*";});return value;}
+return OpenLayers.Class(OpenLayers.Format,{wildcarded:false,srsInBBOX:false,write:function(filter,params){params=params||{};var className=filter.CLASS_NAME;var filterType=className.substring(className.lastIndexOf(".")+1);switch(filterType){case"Spatial":switch(filter.type){case OpenLayers.Filter.Spatial.BBOX:params.bbox=filter.value.toArray();if(this.srsInBBOX&&filter.projection){params.bbox.push(filter.projection.getCode());}
+break;case OpenLayers.Filter.Spatial.DWITHIN:params.tolerance=filter.distance;case OpenLayers.Filter.Spatial.WITHIN:params.lon=filter.value.x;params.lat=filter.value.y;break;default:OpenLayers.Console.warn("Unknown spatial filter type "+filter.type);}
+break;case"Comparison":var op=cmpToStr[filter.type];if(op!==undefined){var value=filter.value;if(filter.type==OpenLayers.Filter.Comparison.LIKE){value=regex2value(value);if(this.wildcarded){value="%"+value+"%";}}
+params[filter.property+"__"+op]=value;params.queryable=params.queryable||[];params.queryable.push(filter.property);}else{OpenLayers.Console.warn("Unknown comparison filter type "+filter.type);}
+break;case"Logical":if(filter.type===OpenLayers.Filter.Logical.AND){for(var i=0,len=filter.filters.length;i<len;i++){params=this.write(filter.filters[i],params);}}else{OpenLayers.Console.warn("Unsupported logical filter type "+filter.type);}
+break;default:OpenLayers.Console.warn("Unknown filter type "+filterType);}
+return params;},CLASS_NAME:"OpenLayers.Format.QueryStringFilter"});})();OpenLayers.Lang["km"]=OpenLayers.Util.applyDefaults({'Permalink':"តំណភ្ជាប់អចិន្ត្រៃយ៍",'Base Layer':"ស្រទាប់បាត​",'Scale = 1 : ${scaleDenom}':"មាត្រដ្ឋាន = ១ ៖ ${scaleDenom}"});OpenLayers.Lang["nl"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Het verzoek is niet afgehandeld met de volgende melding: ${statusText}",'Permalink':"Permanente verwijzing",'Overlays':"Overlays",'Base Layer':"Achtergrondkaart",'noFID':"Een optie die geen FID heeft kan niet bijgewerkt worden.",'browserNotSupported':"Uw browser ondersteunt het weergeven van vectoren niet.\nMomenteel ondersteunde weergavemogelijkheden:\n${renderers}",'minZoomLevelError':"De eigenschap minZoomLevel is alleen bedoeld voor gebruik lagen met die afstammen van FixedZoomLevels-lagen.\nDat deze WFS-laag minZoomLevel controleert, is een overblijfsel uit het verleden.\nWe kunnen deze controle echter niet verwijderen zonder op OL gebaseerde applicaties die hervan afhankelijk zijn stuk te maken.\nDaarom heeft deze functionaliteit de eigenschap \'deprecated\' gekregen - de minZoomLevel wordt verwijderd in versie 3.0.\nGebruik in plaats van deze functie de mogelijkheid om min/max voor resolutie in te stellen zoals op de volgende pagina wordt beschreven:\nhttp://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-transactie: succesvol ${response}",'commitFailed':"WFS-transactie: mislukt ${response}",'googleWarning':"De Google-Layer kon niet correct geladen worden.\x3cbr /\x3e\x3cbr /\x3e\nOm deze melding niet meer te krijgen, moet u een andere achtergrondkaart kiezen in de laagwisselaar in de rechterbovenhoek.\x3cbr /\x3e\x3cbr /\x3e\nDit komt waarschijnlijk doordat de bibliotheek ${layerLib} niet correct ingevoegd is.\x3cbr /\x3e\x3cbr /\x3e\nOntwikkelaars: \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eklik hier\x3c/a\x3e om dit werkend te krijgen.",'getLayerWarning':"De laag ${layerType} kon niet goed geladen worden.\x3cbr /\x3e\x3cbr /\x3e\nOm deze melding niet meer te krijgen, moet u een andere achtergrondkaart kiezen in de laagwisselaar in de rechterbovenhoek.\x3cbr /\x3e\x3cbr /\x3e\nDit komt waarschijnlijk doordat de bibliotheek ${layerLib} niet correct is ingevoegd.\x3cbr /\x3e\x3cbr /\x3e\nOntwikkelaars: \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eklik hier\x3c/a\x3e om dit werkend te krijgen.",'Scale = 1 : ${scaleDenom}':"Schaal = 1 : ${scaleDenom}",'W':"W",'E':"O",'N':"N",'S':"Z",'reprojectDeprecated':"U gebruikt de optie \'reproject\' op de laag ${layerName}.\nDeze optie is vervallen: deze optie was ontwikkeld om gegevens over commerciële basiskaarten weer te geven, maar deze functionaliteit wordt nu bereikt door ondersteuning van Spherical Mercator.\nMeer informatie is beschikbaar op http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Deze methode is verouderd en wordt verwijderd in versie 3.0.\nGebruik ${newMethod}."});OpenLayers.Lang["fr"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Requête non gérée, retournant ${statusText}",'Permalink':"Permalien",'Overlays':"Calques",'Base Layer':"Calque de base",'noFID':"Impossible de mettre à jour un objet sans identifiant (fid).",'browserNotSupported':"Votre navigateur ne supporte pas le rendu vectoriel. Les renderers actuellement supportés sont : \n${renderers}",'minZoomLevelError':"La propriété minZoomLevel doit seulement être utilisée pour des couches FixedZoomLevels-descendent. Le fait que cette couche WFS vérifie la présence de minZoomLevel est une relique du passé. Nous ne pouvons toutefois la supprimer sans casser des applications qui pourraient en dépendre. C\'est pourquoi nous la déprécions -- la vérification du minZoomLevel sera supprimée en version 3.0. A la place, merci d\'utiliser les paramètres de résolutions min/max tel que décrit sur : http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transaction WFS : SUCCES ${response}",'commitFailed':"Transaction WFS : ECHEC ${response}",'googleWarning':"La couche Google n\'a pas été en mesure de se charger correctement.\x3cbr\x3e\x3cbr\x3ePour supprimer ce message, choisissez une nouvelle BaseLayer dans le sélecteur de couche en haut à droite.\x3cbr\x3e\x3cbr\x3eCela est possiblement causé par la non-inclusion de la librairie Google Maps, ou alors parce que la clé de l\'API ne correspond pas à votre site.\x3cbr\x3e\x3cbr\x3eDéveloppeurs : pour savoir comment corriger ceci, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3ecliquez ici\x3c/a\x3e",'getLayerWarning':"La couche ${layerType} n\'est pas en mesure de se charger correctement.\x3cbr\x3e\x3cbr\x3ePour supprimer ce message, choisissez une nouvelle BaseLayer dans le sélecteur de couche en haut à droite.\x3cbr\x3e\x3cbr\x3eCela est possiblement causé par la non-inclusion de la librairie ${layerLib}.\x3cbr\x3e\x3cbr\x3eDéveloppeurs : pour savoir comment corriger ceci, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3ecliquez ici\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Echelle ~ 1 : ${scaleDenom}",'W':"O",'E':"E",'N':"N",'S':"S",'reprojectDeprecated':"Vous utilisez l\'option \'reproject\' sur la couche ${layerName}. Cette option est dépréciée : Son usage permettait d\'afficher des données au dessus de couches raster commerciales.Cette fonctionalité est maintenant supportée en utilisant le support de la projection Mercator Sphérique. Plus d\'information est disponible sur http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Cette méthode est dépréciée, et sera supprimée à la version 3.0. Merci d\'utiliser ${newMethod} à la place.",'proxyNeeded':"Vous avez très probablement besoin de renseigner OpenLayers.ProxyHost pour accéder à ${url}. Voir http://trac.osgeo.org/openlayers/wiki/FrequentlyAskedQuestions#ProxyHost"});OpenLayers.Lang["ksh"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Met dä Antwoot op en Aanfrooch ham_mer nix aanjefange: ${statusText}",'Permalink':"Lengk op Duuer",'Overlays':"Drövver jelaat",'Base Layer':"Jrund-Nivoh",'noFID':"En Saach, woh kein \x3ci lang=\"en\"\x3eFID\x3c/i\x3e för doh es, löht sesch nit ändere.",'browserNotSupported':"Dinge Brauser kann kein Väktore ußjävve. De Zoote Ußjaabe, di em Momang jon, sen:\n${renderers}",'minZoomLevelError':"De Eijeschaff „\x3ccode lang=\"en\"\x3eminZoomLevel\x3c/code\x3e“ es bloß doför jedaach, dat mer se met dä Nivvohß bruch, di vun \x3ccode lang=\"en\"\x3eFixedZoomLevels\x3c/code\x3e affhange don. Dat dat \x3ci lang=\"en\"\x3eWFS\x3c/i\x3e-Nivvoh övverhoup de Eijeschaff „\x3ccode lang=\"en\"\x3eminZoomLevel\x3c/code\x3e“ pröhfe deiht, es noch övveresch vun fröhjer. Mer künne dat ävver jez nit fott lohße, oohne dat mer Jevaa loufe, dat Aanwendunge vun OpenLayers nit mieh loufe, di sesch doh velleijsch noch drop am verlohße sin. Dröm sare mer, dat mer et nit mieh han welle, un de „\x3ccode lang=\"en\"\x3eminZoomLevel\x3c/code\x3e“-Eijeschaff weed hee vun de Version 3.0 af nit mieh jeprööf wäde. Nemm doför de Enstellung för de hühßte un de kleinßte Oplöhsung, esu wi et en http://trac.openlayers.org/wiki/SettingZoomLevels opjeschrevve es.",'commitSuccess':"Dä \x3ci lang=\"en\"\x3eWFS\x3c/i\x3e-Vörjang es joot jeloufe: ${response}",'commitFailed':"Dä \x3ci lang=\"en\"\x3eWFS\x3c/i\x3e-Vörjang es scheif jejange: ${response}",'googleWarning':"Dat Nivvoh \x3ccode lang=\"en\"\x3eGoogle\x3c/code\x3e kunnt nit reschtesch jelaade wääde.\x3cbr /\x3e\x3cbr /\x3eÖm hee di Nohreesch loß ze krijje, donn en ander Jrund-Nivvoh ußsöhke, rähß bovve en de Äk.\x3cbr /\x3e\x3cbr /\x3eWascheinlesch es dat wiel dat \x3ci lang=\"en\"\x3eGoogle-Maps\x3c/i\x3e-Skrepp entweeder nit reschtesch enjebonge wood, udder nit dä reschtejje \x3ci lang=\"en\"\x3eAPI\x3c/i\x3e-Schlößel för Ding Web-ßait scheke deiht.\x3cbr /\x3e\x3cbr /\x3eFör Projrammierer jidd_et Hölp do_drövver, \x3ca href=\"http://trac.openlayers.org/wiki/Google\" target=\"_blank\"\x3ewi mer dat aan et Loufe brengk\x3c/a\x3e.",'getLayerWarning':"Dat Nivvoh \x3ccode\x3e${layerType}\x3c/code\x3e kunnt nit reschtesch jelaade wääde.\x3cbr /\x3e\x3cbr /\x3eÖm hee di Nohreesch loß ze krijje, donn en ander Jrund-Nivvoh ußsöhkre, rähß bovve en de Äk.\x3cbr /\x3e\x3cbr /\x3eWascheinlesch es dat, wiel dat Skrepp \x3ccode\x3e${layerLib}\x3c/code\x3e nit reschtesch enjebonge wood.\x3cbr /\x3e\x3cbr /\x3eFör Projrammierer jidd_Et Hölp do_drövver, \x3ca href=\"http://trac.openlayers.org/wiki/${layerLib}\" target=\"_blank\"\x3ewi mer dat aan et Loufe brengk\x3c/a\x3e.",'Scale = 1 : ${scaleDenom}':"Mohßshtaab = 1 : ${scaleDenom}",'W':"W",'E':"O",'N':"N",'S':"S",'reprojectDeprecated':"Do bruchs de Ußwahl \x3ccode\x3ereproject\x3c/code\x3e op däm Nivvoh \x3ccode\x3e${layerName}\x3c/code\x3e. Di Ußwahl es nit mieh jähn jesinn. Se wohr doför jedaach, öm Date op jeschääfsmäßesch eruß jejovve Kaate bovve drop ze moole, wat ävver enzwesche besser met dä Öngershtözung för de ßfääresche Mäkaator Beldscher jeiht. Doh kanns De mieh drövver fenge op dä Sigg: http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Hee di Metood es nim_mih aktoäll un et weed se en dä Version 3.0 nit mieh jävve. Nemm \x3ccode\x3e${newMethod}\x3c/code\x3e doföör."});OpenLayers.Lang["fur"]=OpenLayers.Util.applyDefaults({'Permalink':"Leam Permanent",'Overlays':"Livei parsore",'Base Layer':"Livel di base",'browserNotSupported':"Il to sgarfadôr nol supuarte la renderizazion vetoriâl. Al moment a son supuartâts:\n${renderers}",'Scale = 1 : ${scaleDenom}':"Scjale = 1 : ${scaleDenom}",'W':"O",'E':"E",'N':"N",'S':"S"});OpenLayers.Lang["ja"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"未処理の要求は ${statusText} を返します",'Permalink':"パーマリンク",'Overlays':"オーバーレイ",'Base Layer':"基底レイヤー",'noFID':"FID のない地物は更新できません。",'browserNotSupported':"あなたのブラウザはベクターグラフィックスの描写に対応していません。現時点で対応しているソフトウェアは以下のものです。\n${renderers}",'minZoomLevelError':"minZoomLevel プロパティは FixedZoomLevels を継承するレイヤーでの使用のみを想定しています。この minZoomLevel に対する WFS レイヤーの検査は歴史的なものです。しかしながら、この検査を除去するとそれに依存する OpenLayers ベースのアプリケーションを破壊してしまう可能性があります。よって廃止が予定されており、この minZoomLevel 検査はバージョン3.0で除去されます。代わりに、http://trac.openlayers.org/wiki/SettingZoomLevels で解説されている、最小および最大解像度設定を使用してください。",'commitSuccess':"WFS トランザクション: 成功 ${response}",'commitFailed':"WFS トランザクション: 失敗 ${response}",'googleWarning':"Google レイヤーが正しく読み込みを行えませんでした。\x3cbr\x3e\x3cbr\x3eこのメッセージを消すには、右上の隅にあるレイヤー切り替え部分で新しい基底レイヤーを選んでください。\x3cbr\x3e\x3cbr\x3eおそらく、これは Google マップ用ライブラリのスクリプトが組み込まれていないか、あなたのサイトに対応する正しい API キーが設定されていないためです。\x3cbr\x3e\x3cbr\x3e開発者の方へ: 正しい動作をさせるために\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eこちらのウィキ\x3c/a\x3eを参照してください。",'getLayerWarning':"${layerType} レイヤーが正しく読み込みを行えませんでした。\x3cbr\x3e\x3cbr\x3eこのメッセージを消すには、右上の隅にあるレイヤー切り替え部分で新しい基底レイヤーを選んでください。\x3cbr\x3e\x3cbr\x3eおそらく、これは ${layerLib} ライブラリのスクリプトが正しく組み込まれていないためです。\x3cbr\x3e\x3cbr\x3e開発者の方へ: 正しい動作をさせるために\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eこちらのウィキ\x3c/a\x3eを参照してください。",'Scale = 1 : ${scaleDenom}':"縮尺 = 1 : ${scaleDenom}",'W':"西",'E':"東",'N':"北",'S':"南",'reprojectDeprecated':"あなたは「${layerName}」レイヤーで reproject オプションを使っています。このオプションは商用の基底地図上に情報を表示する目的で設計されましたが、現在ではその機能は Spherical Mercator サポートを利用して実現されており、このオプションの使用は非推奨です。追加の情報は http://trac.openlayers.org/wiki/SphericalMercator で入手できます。",'methodDeprecated':"このメソッドは廃止が予定されており、バージョン3.0で除去されます。代わりに ${newMethod} を使用してください。"});(function(){var oXMLHttpRequest=window.XMLHttpRequest;var bGecko=!!window.controllers,bIE=window.document.all&&!window.opera,bIE7=bIE&&window.navigator.userAgent.match(/MSIE 7.0/);function fXMLHttpRequest(){this._object=oXMLHttpRequest&&!bIE7?new oXMLHttpRequest:new window.ActiveXObject("Microsoft.XMLHTTP");this._listeners=[];};function cXMLHttpRequest(){return new fXMLHttpRequest;};cXMLHttpRequest.prototype=fXMLHttpRequest.prototype;if(bGecko&&oXMLHttpRequest.wrapped)
+cXMLHttpRequest.wrapped=oXMLHttpRequest.wrapped;cXMLHttpRequest.UNSENT=0;cXMLHttpRequest.OPENED=1;cXMLHttpRequest.HEADERS_RECEIVED=2;cXMLHttpRequest.LOADING=3;cXMLHttpRequest.DONE=4;cXMLHttpRequest.prototype.readyState=cXMLHttpRequest.UNSENT;cXMLHttpRequest.prototype.responseText='';cXMLHttpRequest.prototype.responseXML=null;cXMLHttpRequest.prototype.status=0;cXMLHttpRequest.prototype.statusText='';cXMLHttpRequest.prototype.priority="NORMAL";cXMLHttpRequest.prototype.onreadystatechange=null;cXMLHttpRequest.onreadystatechange=null;cXMLHttpRequest.onopen=null;cXMLHttpRequest.onsend=null;cXMLHttpRequest.onabort=null;cXMLHttpRequest.prototype.open=function(sMethod,sUrl,bAsync,sUser,sPassword){delete this._headers;if(arguments.length<3)
+bAsync=true;this._async=bAsync;var oRequest=this,nState=this.readyState,fOnUnload;if(bIE&&bAsync){fOnUnload=function(){if(nState!=cXMLHttpRequest.DONE){fCleanTransport(oRequest);oRequest.abort();}};window.attachEvent("onunload",fOnUnload);}
+if(cXMLHttpRequest.onopen)
+cXMLHttpRequest.onopen.apply(this,arguments);if(arguments.length>4)
+this._object.open(sMethod,sUrl,bAsync,sUser,sPassword);else
+if(arguments.length>3)
+this._object.open(sMethod,sUrl,bAsync,sUser);else
+this._object.open(sMethod,sUrl,bAsync);this.readyState=cXMLHttpRequest.OPENED;fReadyStateChange(this);this._object.onreadystatechange=function(){if(bGecko&&!bAsync)
+return;oRequest.readyState=oRequest._object.readyState;fSynchronizeValues(oRequest);if(oRequest._aborted){oRequest.readyState=cXMLHttpRequest.UNSENT;return;}
+if(oRequest.readyState==cXMLHttpRequest.DONE){delete oRequest._data;fCleanTransport(oRequest);if(bIE&&bAsync)
+window.detachEvent("onunload",fOnUnload);}
+if(nState!=oRequest.readyState)
+fReadyStateChange(oRequest);nState=oRequest.readyState;}};function fXMLHttpRequest_send(oRequest){oRequest._object.send(oRequest._data);if(bGecko&&!oRequest._async){oRequest.readyState=cXMLHttpRequest.OPENED;fSynchronizeValues(oRequest);while(oRequest.readyState<cXMLHttpRequest.DONE){oRequest.readyState++;fReadyStateChange(oRequest);if(oRequest._aborted)
+return;}}};cXMLHttpRequest.prototype.send=function(vData){if(cXMLHttpRequest.onsend)
+cXMLHttpRequest.onsend.apply(this,arguments);if(!arguments.length)
+vData=null;if(vData&&vData.nodeType){vData=window.XMLSerializer?new window.XMLSerializer().serializeToString(vData):vData.xml;if(!this._headers["Content-Type"])
+this._object.setRequestHeader("Content-Type","application/xml");}
+this._data=vData;fXMLHttpRequest_send(this);};cXMLHttpRequest.prototype.abort=function(){if(cXMLHttpRequest.onabort)
+cXMLHttpRequest.onabort.apply(this,arguments);if(this.readyState>cXMLHttpRequest.UNSENT)
+this._aborted=true;this._object.abort();fCleanTransport(this);this.readyState=cXMLHttpRequest.UNSENT;delete this._data;};cXMLHttpRequest.prototype.getAllResponseHeaders=function(){return this._object.getAllResponseHeaders();};cXMLHttpRequest.prototype.getResponseHeader=function(sName){return this._object.getResponseHeader(sName);};cXMLHttpRequest.prototype.setRequestHeader=function(sName,sValue){if(!this._headers)
+this._headers={};this._headers[sName]=sValue;return this._object.setRequestHeader(sName,sValue);};cXMLHttpRequest.prototype.addEventListener=function(sName,fHandler,bUseCapture){for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++)
+if(oListener[0]==sName&&oListener[1]==fHandler&&oListener[2]==bUseCapture)
+return;this._listeners.push([sName,fHandler,bUseCapture]);};cXMLHttpRequest.prototype.removeEventListener=function(sName,fHandler,bUseCapture){for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++)
+if(oListener[0]==sName&&oListener[1]==fHandler&&oListener[2]==bUseCapture)
+break;if(oListener)
+this._listeners.splice(nIndex,1);};cXMLHttpRequest.prototype.dispatchEvent=function(oEvent){var oEventPseudo={'type':oEvent.type,'target':this,'currentTarget':this,'eventPhase':2,'bubbles':oEvent.bubbles,'cancelable':oEvent.cancelable,'timeStamp':oEvent.timeStamp,'stopPropagation':function(){},'preventDefault':function(){},'initEvent':function(){}};if(oEventPseudo.type=="readystatechange"&&this.onreadystatechange)
+(this.onreadystatechange.handleEvent||this.onreadystatechange).apply(this,[oEventPseudo]);for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++)
+if(oListener[0]==oEventPseudo.type&&!oListener[2])
+(oListener[1].handleEvent||oListener[1]).apply(this,[oEventPseudo]);};cXMLHttpRequest.prototype.toString=function(){return'['+"object"+' '+"XMLHttpRequest"+']';};cXMLHttpRequest.toString=function(){return'['+"XMLHttpRequest"+']';};function fReadyStateChange(oRequest){if(cXMLHttpRequest.onreadystatechange)
+cXMLHttpRequest.onreadystatechange.apply(oRequest);oRequest.dispatchEvent({'type':"readystatechange",'bubbles':false,'cancelable':false,'timeStamp':new Date+0});};function fGetDocument(oRequest){var oDocument=oRequest.responseXML,sResponse=oRequest.responseText;if(bIE&&sResponse&&oDocument&&!oDocument.documentElement&&oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)){oDocument=new window.ActiveXObject("Microsoft.XMLDOM");oDocument.async=false;oDocument.validateOnParse=false;oDocument.loadXML(sResponse);}
+if(oDocument)
+if((bIE&&oDocument.parseError!=0)||!oDocument.documentElement||(oDocument.documentElement&&oDocument.documentElement.tagName=="parsererror"))
+return null;return oDocument;};function fSynchronizeValues(oRequest){try{oRequest.responseText=oRequest._object.responseText;}catch(e){}
+try{oRequest.responseXML=fGetDocument(oRequest._object);}catch(e){}
+try{oRequest.status=oRequest._object.status;}catch(e){}
+try{oRequest.statusText=oRequest._object.statusText;}catch(e){}};function fCleanTransport(oRequest){oRequest._object.onreadystatechange=new window.Function;};if(!window.Function.prototype.apply){window.Function.prototype.apply=function(oRequest,oArguments){if(!oArguments)
+oArguments=[];oRequest.__func=this;oRequest.__func(oArguments[0],oArguments[1],oArguments[2],oArguments[3],oArguments[4]);delete oRequest.__func;};};OpenLayers.Request.XMLHttpRequest=cXMLHttpRequest;})();OpenLayers.Lang["nds"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Unbehannelt Trüchmellels för de Anfraag ${statusText}",'Permalink':"Permalink",'Overlays':"Overlays",'Base Layer':"Achtergrundkoort",'noFID':"En Feature, dat keen FID hett, kann nich aktuell maakt warrn.",'browserNotSupported':"Dien Browser ünnerstütt keen Vektorbiller. Ünnerstütt Renderers:\n${renderers}",'commitSuccess':"WFS-Transakschoon: hett klappt ${response}",'commitFailed':"WFS-Transakschoon: hett nich klappt ${response}",'Scale = 1 : ${scaleDenom}':"Skaal = 1 : ${scaleDenom}",'methodDeprecated':"Disse Methood is oold un schall dat in 3.0 nich mehr geven. Bruuk dor man beter ${newMethod} för."});OpenLayers.Handler.RegularPolygon=OpenLayers.Class(OpenLayers.Handler.Drag,{sides:4,radius:null,snapAngle:null,snapToggle:'shiftKey',layerOptions:null,persist:false,irregular:false,citeCompliant:false,angle:null,fixedRadius:false,feature:null,layer:null,origin:null,initialize:function(control,callbacks,options){if(!(options&&options.layerOptions&&options.layerOptions.styleMap)){this.style=OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'],{});}
+OpenLayers.Handler.Drag.prototype.initialize.apply(this,[control,callbacks,options]);this.options=(options)?options:{};},setOptions:function(newOptions){OpenLayers.Util.extend(this.options,newOptions);OpenLayers.Util.extend(this,newOptions);},activate:function(){var activated=false;if(OpenLayers.Handler.Drag.prototype.activate.apply(this,arguments)){var options=OpenLayers.Util.extend({displayInLayerSwitcher:false,calculateInRange:OpenLayers.Function.True,wrapDateLine:this.citeCompliant},this.layerOptions);this.layer=new OpenLayers.Layer.Vector(this.CLASS_NAME,options);this.map.addLayer(this.layer);activated=true;}
+return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.Drag.prototype.deactivate.apply(this,arguments)){if(this.dragging){this.cancel();}
+if(this.layer.map!=null){this.layer.destroy(false);if(this.feature){this.feature.destroy();}}
+this.layer=null;this.feature=null;deactivated=true;}
+return deactivated;},down:function(evt){this.fixedRadius=!!(this.radius);var maploc=this.layer.getLonLatFromViewPortPx(evt.xy);this.origin=new OpenLayers.Geometry.Point(maploc.lon,maploc.lat);if(!this.fixedRadius||this.irregular){this.radius=this.map.getResolution();}
+if(this.persist){this.clear();}
+this.feature=new OpenLayers.Feature.Vector();this.createGeometry();this.callback("create",[this.origin,this.feature]);this.layer.addFeatures([this.feature],{silent:true});this.layer.drawFeature(this.feature,this.style);},move:function(evt){var maploc=this.layer.getLonLatFromViewPortPx(evt.xy);var point=new OpenLayers.Geometry.Point(maploc.lon,maploc.lat);if(this.irregular){var ry=Math.sqrt(2)*Math.abs(point.y-this.origin.y)/2;this.radius=Math.max(this.map.getResolution()/2,ry);}else if(this.fixedRadius){this.origin=point;}else{this.calculateAngle(point,evt);this.radius=Math.max(this.map.getResolution()/2,point.distanceTo(this.origin));}
+this.modifyGeometry();if(this.irregular){var dx=point.x-this.origin.x;var dy=point.y-this.origin.y;var ratio;if(dy==0){ratio=dx/(this.radius*Math.sqrt(2));}else{ratio=dx/dy;}
+this.feature.geometry.resize(1,this.origin,ratio);this.feature.geometry.move(dx/2,dy/2);}
+this.layer.drawFeature(this.feature,this.style);},up:function(evt){this.finalize();if(this.start==this.last){this.callback("done",[evt.xy]);}},out:function(evt){this.finalize();},createGeometry:function(){this.angle=Math.PI*((1/this.sides)-(1/2));if(this.snapAngle){this.angle+=this.snapAngle*(Math.PI/180);}
+this.feature.geometry=OpenLayers.Geometry.Polygon.createRegularPolygon(this.origin,this.radius,this.sides,this.snapAngle);},modifyGeometry:function(){var angle,point;var ring=this.feature.geometry.components[0];if(ring.components.length!=(this.sides+1)){this.createGeometry();ring=this.feature.geometry.components[0];}
+for(var i=0;i<this.sides;++i){point=ring.components[i];angle=this.angle+(i*2*Math.PI/this.sides);point.x=this.origin.x+(this.radius*Math.cos(angle));point.y=this.origin.y+(this.radius*Math.sin(angle));point.clearBounds();}},calculateAngle:function(point,evt){var alpha=Math.atan2(point.y-this.origin.y,point.x-this.origin.x);if(this.snapAngle&&(this.snapToggle&&!evt[this.snapToggle])){var snapAngleRad=(Math.PI/180)*this.snapAngle;this.angle=Math.round(alpha/snapAngleRad)*snapAngleRad;}else{this.angle=alpha;}},cancel:function(){this.callback("cancel",null);this.finalize();},finalize:function(){this.origin=null;this.radius=this.options.radius;},clear:function(){if(this.layer){this.layer.renderer.clear();this.layer.destroyFeatures();}},callback:function(name,args){if(this.callbacks[name]){this.callbacks[name].apply(this.control,[this.feature.geometry.clone()]);}
+if(!this.persist&&(name=="done"||name=="cancel")){this.clear();}},CLASS_NAME:"OpenLayers.Handler.RegularPolygon"});OpenLayers.Renderer.VML=OpenLayers.Class(OpenLayers.Renderer.Elements,{xmlns:"urn:schemas-microsoft-com:vml",symbolCache:{},offset:null,initialize:function(containerID){if(!this.supported()){return;}
+if(!document.namespaces.olv){document.namespaces.add("olv",this.xmlns);var style=document.createStyleSheet();var shapes=['shape','rect','oval','fill','stroke','imagedata','group','textbox'];for(var i=0,len=shapes.length;i<len;i++){style.addRule('olv\\:'+shapes[i],"behavior: url(#default#VML); "+"position: absolute; display: inline-block;");}}
+OpenLayers.Renderer.Elements.prototype.initialize.apply(this,arguments);},supported:function(){return!!(document.namespaces);},setExtent:function(extent,resolutionChanged){var coordSysUnchanged=OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,arguments);var resolution=this.getResolution();var left=(extent.left/resolution)|0;var top=(extent.top/resolution-this.size.h)|0;if(resolutionChanged||!this.offset){this.offset={x:left,y:top};left=0;top=0;}else{left=left-this.offset.x;top=top-this.offset.y;}
+var org=(left-this.xOffset)+" "+top;this.root.coordorigin=org;var roots=[this.root,this.vectorRoot,this.textRoot];var root;for(var i=0,len=roots.length;i<len;++i){root=roots[i];var size=this.size.w+" "+this.size.h;root.coordsize=size;}
+this.root.style.flip="y";return coordSysUnchanged;},setSize:function(size){OpenLayers.Renderer.prototype.setSize.apply(this,arguments);var roots=[this.rendererRoot,this.root,this.vectorRoot,this.textRoot];var w=this.size.w+"px";var h=this.size.h+"px";var root;for(var i=0,len=roots.length;i<len;++i){root=roots[i];root.style.width=w;root.style.height=h;}},getNodeType:function(geometry,style){var nodeType=null;switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":if(style.externalGraphic){nodeType="olv:rect";}else if(this.isComplexSymbol(style.graphicName)){nodeType="olv:shape";}else{nodeType="olv:oval";}
+break;case"OpenLayers.Geometry.Rectangle":nodeType="olv:rect";break;case"OpenLayers.Geometry.LineString":case"OpenLayers.Geometry.LinearRing":case"OpenLayers.Geometry.Polygon":case"OpenLayers.Geometry.Curve":nodeType="olv:shape";break;default:break;}
+return nodeType;},setStyle:function(node,style,options,geometry){style=style||node._style;options=options||node._options;var fillColor=style.fillColor;if(node._geometryClass==="OpenLayers.Geometry.Point"){if(style.externalGraphic){options.isFilled=true;if(style.graphicTitle){node.title=style.graphicTitle;}
+var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;var resolution=this.getResolution();var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset:-(0.5*height);node.style.left=((((geometry.x-this.featureDx)/resolution-this.offset.x)+xOffset)|0)+"px";node.style.top=(((geometry.y/resolution-this.offset.y)-(yOffset+height))|0)+"px";node.style.width=width+"px";node.style.height=height+"px";node.style.flip="y";fillColor="none";options.isStroked=false;}else if(this.isComplexSymbol(style.graphicName)){var cache=this.importSymbol(style.graphicName);node.path=cache.path;node.coordorigin=cache.left+","+cache.bottom;var size=cache.size;node.coordsize=size+","+size;this.drawCircle(node,geometry,style.pointRadius);node.style.flip="y";}else{this.drawCircle(node,geometry,style.pointRadius);}}
+if(options.isFilled){node.fillcolor=fillColor;}else{node.filled="false";}
+var fills=node.getElementsByTagName("fill");var fill=(fills.length==0)?null:fills[0];if(!options.isFilled){if(fill){node.removeChild(fill);}}else{if(!fill){fill=this.createNode('olv:fill',node.id+"_fill");}
+fill.opacity=style.fillOpacity;if(node._geometryClass==="OpenLayers.Geometry.Point"&&style.externalGraphic){if(style.graphicOpacity){fill.opacity=style.graphicOpacity;}
+fill.src=style.externalGraphic;fill.type="frame";if(!(style.graphicWidth&&style.graphicHeight)){fill.aspect="atmost";}}
+if(fill.parentNode!=node){node.appendChild(fill);}}
+var rotation=style.rotation;if((rotation!==undefined||node._rotation!==undefined)){node._rotation=rotation;if(style.externalGraphic){this.graphicRotate(node,xOffset,yOffset,style);fill.opacity=0;}else if(node._geometryClass==="OpenLayers.Geometry.Point"){node.style.rotation=rotation||0;}}
+var strokes=node.getElementsByTagName("stroke");var stroke=(strokes.length==0)?null:strokes[0];if(!options.isStroked){node.stroked=false;if(stroke){stroke.on=false;}}else{if(!stroke){stroke=this.createNode('olv:stroke',node.id+"_stroke");node.appendChild(stroke);}
+stroke.on=true;stroke.color=style.strokeColor;stroke.weight=style.strokeWidth+"px";stroke.opacity=style.strokeOpacity;stroke.endcap=style.strokeLinecap=='butt'?'flat':(style.strokeLinecap||'round');if(style.strokeDashstyle){stroke.dashstyle=this.dashStyle(style);}}
+if(style.cursor!="inherit"&&style.cursor!=null){node.style.cursor=style.cursor;}
+return node;},graphicRotate:function(node,xOffset,yOffset,style){var style=style||node._style;var rotation=style.rotation||0;var aspectRatio,size;if(!(style.graphicWidth&&style.graphicHeight)){var img=new Image();img.onreadystatechange=OpenLayers.Function.bind(function(){if(img.readyState=="complete"||img.readyState=="interactive"){aspectRatio=img.width/img.height;size=Math.max(style.pointRadius*2,style.graphicWidth||0,style.graphicHeight||0);xOffset=xOffset*aspectRatio;style.graphicWidth=size*aspectRatio;style.graphicHeight=size;this.graphicRotate(node,xOffset,yOffset,style);}},this);img.src=style.externalGraphic;return;}else{size=Math.max(style.graphicWidth,style.graphicHeight);aspectRatio=style.graphicWidth/style.graphicHeight;}
+var width=Math.round(style.graphicWidth||size*aspectRatio);var height=Math.round(style.graphicHeight||size);node.style.width=width+"px";node.style.height=height+"px";var image=document.getElementById(node.id+"_image");if(!image){image=this.createNode("olv:imagedata",node.id+"_image");node.appendChild(image);}
+image.style.width=width+"px";image.style.height=height+"px";image.src=style.externalGraphic;image.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader("+"src='', sizingMethod='scale')";var rot=rotation*Math.PI/180;var sintheta=Math.sin(rot);var costheta=Math.cos(rot);var filter="progid:DXImageTransform.Microsoft.Matrix(M11="+costheta+",M12="+(-sintheta)+",M21="+sintheta+",M22="+costheta+",SizingMethod='auto expand')\n";var opacity=style.graphicOpacity||style.fillOpacity;if(opacity&&opacity!=1){filter+="progid:DXImageTransform.Microsoft.BasicImage(opacity="+
+opacity+")\n";}
+node.style.filter=filter;var centerPoint=new OpenLayers.Geometry.Point(-xOffset,-yOffset);var imgBox=new OpenLayers.Bounds(0,0,width,height).toGeometry();imgBox.rotate(style.rotation,centerPoint);var imgBounds=imgBox.getBounds();node.style.left=Math.round(parseInt(node.style.left)+imgBounds.left)+"px";node.style.top=Math.round(parseInt(node.style.top)-imgBounds.bottom)+"px";},postDraw:function(node){node.style.visibility="visible";var fillColor=node._style.fillColor;var strokeColor=node._style.strokeColor;if(fillColor=="none"&&node.fillcolor!=fillColor){node.fillcolor=fillColor;}
+if(strokeColor=="none"&&node.strokecolor!=strokeColor){node.strokecolor=strokeColor;}},setNodeDimension:function(node,geometry){var bbox=geometry.getBounds();if(bbox){var resolution=this.getResolution();var scaledBox=new OpenLayers.Bounds(((bbox.left-this.featureDx)/resolution-this.offset.x)|0,(bbox.bottom/resolution-this.offset.y)|0,((bbox.right-this.featureDx)/resolution-this.offset.x)|0,(bbox.top/resolution-this.offset.y)|0);node.style.left=scaledBox.left+"px";node.style.top=scaledBox.top+"px";node.style.width=scaledBox.getWidth()+"px";node.style.height=scaledBox.getHeight()+"px";node.coordorigin=scaledBox.left+" "+scaledBox.top;node.coordsize=scaledBox.getWidth()+" "+scaledBox.getHeight();}},dashStyle:function(style){var dash=style.strokeDashstyle;switch(dash){case'solid':case'dot':case'dash':case'dashdot':case'longdash':case'longdashdot':return dash;default:var parts=dash.split(/[ ,]/);if(parts.length==2){if(1*parts[0]>=2*parts[1]){return"longdash";}
+return(parts[0]==1||parts[1]==1)?"dot":"dash";}else if(parts.length==4){return(1*parts[0]>=2*parts[1])?"longdashdot":"dashdot";}
+return"solid";}},createNode:function(type,id){var node=document.createElement(type);if(id){node.id=id;}
+node.unselectable='on';node.onselectstart=OpenLayers.Function.False;return node;},nodeTypeCompare:function(node,type){var subType=type;var splitIndex=subType.indexOf(":");if(splitIndex!=-1){subType=subType.substr(splitIndex+1);}
+var nodeName=node.nodeName;splitIndex=nodeName.indexOf(":");if(splitIndex!=-1){nodeName=nodeName.substr(splitIndex+1);}
+return(subType==nodeName);},createRenderRoot:function(){return this.nodeFactory(this.container.id+"_vmlRoot","div");},createRoot:function(suffix){return this.nodeFactory(this.container.id+suffix,"olv:group");},drawPoint:function(node,geometry){return this.drawCircle(node,geometry,1);},drawCircle:function(node,geometry,radius){if(!isNaN(geometry.x)&&!isNaN(geometry.y)){var resolution=this.getResolution();node.style.left=((((geometry.x-this.featureDx)/resolution-this.offset.x)|0)-radius)+"px";node.style.top=(((geometry.y/resolution-this.offset.y)|0)-radius)+"px";var diameter=radius*2;node.style.width=diameter+"px";node.style.height=diameter+"px";return node;}
+return false;},drawLineString:function(node,geometry){return this.drawLine(node,geometry,false);},drawLinearRing:function(node,geometry){return this.drawLine(node,geometry,true);},drawLine:function(node,geometry,closeLine){this.setNodeDimension(node,geometry);var resolution=this.getResolution();var numComponents=geometry.components.length;var parts=new Array(numComponents);var comp,x,y;for(var i=0;i<numComponents;i++){comp=geometry.components[i];x=((comp.x-this.featureDx)/resolution-this.offset.x)|0;y=(comp.y/resolution-this.offset.y)|0;parts[i]=" "+x+","+y+" l ";}
+var end=(closeLine)?" x e":" e";node.path="m"+parts.join("")+end;return node;},drawPolygon:function(node,geometry){this.setNodeDimension(node,geometry);var resolution=this.getResolution();var path=[];var j,jj,points,area,first,second,i,ii,comp,pathComp,x,y;for(j=0,jj=geometry.components.length;j<jj;j++){path.push("m");points=geometry.components[j].components;area=(j===0);first=null;second=null;for(i=0,ii=points.length;i<ii;i++){comp=points[i];x=((comp.x-this.featureDx)/resolution-this.offset.x)|0;y=(comp.y/resolution-this.offset.y)|0;pathComp=" "+x+","+y;path.push(pathComp);if(i==0){path.push(" l");}
+if(!area){if(!first){first=pathComp;}else if(first!=pathComp){if(!second){second=pathComp;}else if(second!=pathComp){area=true;}}}}
+path.push(area?" x ":" ");}
+path.push("e");node.path=path.join("");return node;},drawRectangle:function(node,geometry){var resolution=this.getResolution();node.style.left=(((geometry.x-this.featureDx)/resolution-this.offset.x)|0)+"px";node.style.top=((geometry.y/resolution-this.offset.y)|0)+"px";node.style.width=((geometry.width/resolution)|0)+"px";node.style.height=((geometry.height/resolution)|0)+"px";return node;},drawText:function(featureId,style,location){var label=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX,"olv:rect");var textbox=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX+"_textbox","olv:textbox");var resolution=this.getResolution();label.style.left=(((location.x-this.featureDx)/resolution-this.offset.x)|0)+"px";label.style.top=((location.y/resolution-this.offset.y)|0)+"px";label.style.flip="y";textbox.innerText=style.label;if(style.cursor!="inherit"&&style.cursor!=null){textbox.style.cursor=style.cursor;}
+if(style.fontColor){textbox.style.color=style.fontColor;}
+if(style.fontOpacity){textbox.style.filter='alpha(opacity='+(style.fontOpacity*100)+')';}
+if(style.fontFamily){textbox.style.fontFamily=style.fontFamily;}
+if(style.fontSize){textbox.style.fontSize=style.fontSize;}
+if(style.fontWeight){textbox.style.fontWeight=style.fontWeight;}
+if(style.fontStyle){textbox.style.fontStyle=style.fontStyle;}
+if(style.labelSelect===true){label._featureId=featureId;textbox._featureId=featureId;textbox._geometry=location;textbox._geometryClass=location.CLASS_NAME;}
+textbox.style.whiteSpace="nowrap";textbox.inset="1px,0px,0px,0px";if(!label.parentNode){label.appendChild(textbox);this.textRoot.appendChild(label);}
+var align=style.labelAlign||"cm";if(align.length==1){align+="m";}
+var xshift=textbox.clientWidth*(OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(0,1)]);var yshift=textbox.clientHeight*(OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(1,1)]);label.style.left=parseInt(label.style.left)-xshift-1+"px";label.style.top=parseInt(label.style.top)+yshift+"px";},moveRoot:function(renderer){var layer=this.map.getLayer(renderer.container.id);if(layer instanceof OpenLayers.Layer.Vector.RootContainer){layer=this.map.getLayer(this.container.id);}
+layer&&layer.renderer.clear();OpenLayers.Renderer.Elements.prototype.moveRoot.apply(this,arguments);layer&&layer.redraw();},importSymbol:function(graphicName){var id=this.container.id+"-"+graphicName;var cache=this.symbolCache[id];if(cache){return cache;}
+var symbol=OpenLayers.Renderer.symbol[graphicName];if(!symbol){throw new Error(graphicName+' is not a valid symbol name');}
+var symbolExtent=new OpenLayers.Bounds(Number.MAX_VALUE,Number.MAX_VALUE,0,0);var pathitems=["m"];for(var i=0;i<symbol.length;i=i+2){var x=symbol[i];var y=symbol[i+1];symbolExtent.left=Math.min(symbolExtent.left,x);symbolExtent.bottom=Math.min(symbolExtent.bottom,y);symbolExtent.right=Math.max(symbolExtent.right,x);symbolExtent.top=Math.max(symbolExtent.top,y);pathitems.push(x);pathitems.push(y);if(i==0){pathitems.push("l");}}
+pathitems.push("x e");var path=pathitems.join(" ");var diff=(symbolExtent.getWidth()-symbolExtent.getHeight())/2;if(diff>0){symbolExtent.bottom=symbolExtent.bottom-diff;symbolExtent.top=symbolExtent.top+diff;}else{symbolExtent.left=symbolExtent.left+diff;symbolExtent.right=symbolExtent.right-diff;}
+cache={path:path,size:symbolExtent.getWidth(),left:symbolExtent.left,bottom:symbolExtent.bottom};this.symbolCache[id]=cache;return cache;},CLASS_NAME:"OpenLayers.Renderer.VML"});OpenLayers.Renderer.VML.LABEL_SHIFT={"l":0,"c":.5,"r":1,"t":0,"m":.5,"b":1};OpenLayers.Lang["vi"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Không xử lý được phản hồi ${statusText} cho yêu cầu",'Permalink':"Liên kết thường trực",'Overlays':"Lấp bản đồ",'Base Layer':"Lớp nền",'noFID':"Không thể cập nhật tính năng thiếu FID.",'browserNotSupported':"Trình duyệt của bạn không hỗ trợ chức năng vẽ bằng vectơ. Hiện hỗ trợ các bộ kết xuất:\n${renderers}",'minZoomLevelError':"Chỉ nên sử dụng thuộc tính minZoomLevel với các lớp FixedZoomLevels-descendent. Việc lớp wfs này tìm cho minZoomLevel là di tích còn lại từ xưa. Tuy nhiên, nếu chúng tôi dời nó thì sẽ vỡ các chương trình OpenLayers mà dựa trên nó. Bởi vậy chúng tôi phản đối sử dụng nó\x26nbsp;– bước tìm cho minZoomLevel sẽ được dời vào phiên bản 3.0. Xin sử dụng thiết lập độ phân tích tối thiểu / tối đa thay thế, theo hướng dẫn này: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Giao dịch WFS: THÀNH CÔNG ${response}",'commitFailed':"Giao dịch WFS: THẤT BẠI ${response}",'googleWarning':"Không thể tải lớp Google đúng đắn.\x3cbr\x3e\x3cbr\x3eĐể tránh thông báo này lần sau, hãy chọn BaseLayer mới dùng điều khiển chọn lớp ở góc trên phải.\x3cbr\x3e\x3cbr\x3eChắc script thư viện Google Maps hoặc không được bao gồm hoặc không chứa khóa API hợp với website của bạn.\x3cbr\x3e\x3cbr\x3e\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eTrợ giúp về tính năng này\x3c/a\x3e cho người phát triển.",'getLayerWarning':"Không thể tải lớp ${layerType} đúng đắn.\x3cbr\x3e\x3cbr\x3eĐể tránh thông báo này lần sau, hãy chọn BaseLayer mới dùng điều khiển chọn lớp ở góc trên phải.\x3cbr\x3e\x3cbr\x3eChắc script thư viện ${layerLib} không được bao gồm đúng kiểu.\x3cbr\x3e\x3cbr\x3e\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eTrợ giúp về tính năng này\x3c/a\x3e cho người phát triển.",'Scale = 1 : ${scaleDenom}':"Tỷ lệ = 1 : ${scaleDenom}",'W':"T",'E':"Đ",'N':"B",'S':"N",'reprojectDeprecated':"Bạn đang áp dụng chế độ “reproject” vào lớp ${layerName}. Chế độ này đã bị phản đối: nó có mục đích hỗ trợ lấp dữ liệu trên các nền bản đồ thương mại; nên thực hiện hiệu ứng đó dùng tính năng Mercator Hình cầu. Có sẵn thêm chi tiết tại http://trac.openlayers.org/wiki/SphericalMercator .",'methodDeprecated':"Phương thức này đã bị phản đối và sẽ bị dời vào phiên bản 3.0. Xin hãy sử dụng ${newMethod} thay thế."});OpenLayers.Protocol=OpenLayers.Class({format:null,options:null,autoDestroy:true,defaultFilter:null,initialize:function(options){options=options||{};OpenLayers.Util.extend(this,options);this.options=options;},mergeWithDefaultFilter:function(filter){var merged;if(filter&&this.defaultFilter){merged=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND,filters:[this.defaultFilter,filter]});}else{merged=filter||this.defaultFilter||undefined;}
+return merged;},destroy:function(){this.options=null;this.format=null;},read:function(options){options=options||{};options.filter=this.mergeWithDefaultFilter(options.filter);},create:function(){},update:function(){},"delete":function(){},commit:function(){},abort:function(response){},createCallback:function(method,response,options){return OpenLayers.Function.bind(function(){method.apply(this,[response,options]);},this);},CLASS_NAME:"OpenLayers.Protocol"});OpenLayers.Protocol.Response=OpenLayers.Class({code:null,requestType:null,last:true,features:null,data:null,reqFeatures:null,priv:null,error:null,initialize:function(options){OpenLayers.Util.extend(this,options);},success:function(){return this.code>0;},CLASS_NAME:"OpenLayers.Protocol.Response"});OpenLayers.Protocol.Response.SUCCESS=1;OpenLayers.Protocol.Response.FAILURE=0;OpenLayers.Protocol.HTTP=OpenLayers.Class(OpenLayers.Protocol,{url:null,headers:null,params:null,callback:null,scope:null,readWithPOST:false,updateWithPOST:false,deleteWithPOST:false,wildcarded:false,srsInBBOX:false,initialize:function(options){options=options||{};this.params={};this.headers={};OpenLayers.Protocol.prototype.initialize.apply(this,arguments);if(!this.filterToParams&&OpenLayers.Format.QueryStringFilter){var format=new OpenLayers.Format.QueryStringFilter({wildcarded:this.wildcarded,srsInBBOX:this.srsInBBOX});this.filterToParams=function(filter,params){return format.write(filter,params);};}},destroy:function(){this.params=null;this.headers=null;OpenLayers.Protocol.prototype.destroy.apply(this);},read:function(options){OpenLayers.Protocol.prototype.read.apply(this,arguments);options=options||{};options.params=OpenLayers.Util.applyDefaults(options.params,this.options.params);options=OpenLayers.Util.applyDefaults(options,this.options);if(options.filter&&this.filterToParams){options.params=this.filterToParams(options.filter,options.params);}
+var readWithPOST=(options.readWithPOST!==undefined)?options.readWithPOST:this.readWithPOST;var resp=new OpenLayers.Protocol.Response({requestType:"read"});if(readWithPOST){var headers=options.headers||{};headers["Content-Type"]="application/x-www-form-urlencoded";resp.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleRead,resp,options),data:OpenLayers.Util.getParameterString(options.params),headers:headers});}else{resp.priv=OpenLayers.Request.GET({url:options.url,callback:this.createCallback(this.handleRead,resp,options),params:options.params,headers:options.headers});}
+return resp;},handleRead:function(resp,options){this.handleResponse(resp,options);},create:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:features,requestType:"create"});resp.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleCreate,resp,options),headers:options.headers,data:this.format.write(features)});return resp;},handleCreate:function(resp,options){this.handleResponse(resp,options);},update:function(feature,options){options=options||{};var url=options.url||feature.url||this.options.url+"/"+feature.fid;options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:feature,requestType:"update"});var method=this.updateWithPOST?"POST":"PUT";resp.priv=OpenLayers.Request[method]({url:url,callback:this.createCallback(this.handleUpdate,resp,options),headers:options.headers,data:this.format.write(feature)});return resp;},handleUpdate:function(resp,options){this.handleResponse(resp,options);},"delete":function(feature,options){options=options||{};var url=options.url||feature.url||this.options.url+"/"+feature.fid;options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:feature,requestType:"delete"});var method=this.deleteWithPOST?"POST":"DELETE";var requestOptions={url:url,callback:this.createCallback(this.handleDelete,resp,options),headers:options.headers};if(this.deleteWithPOST){requestOptions.data=this.format.write(feature);}
+resp.priv=OpenLayers.Request[method](requestOptions);return resp;},handleDelete:function(resp,options){this.handleResponse(resp,options);},handleResponse:function(resp,options){var request=resp.priv;if(options.callback){if(request.status>=200&&request.status<300){if(resp.requestType!="delete"){resp.features=this.parseFeatures(request);}
+resp.code=OpenLayers.Protocol.Response.SUCCESS;}else{resp.code=OpenLayers.Protocol.Response.FAILURE;}
+options.callback.call(options.scope,resp);}},parseFeatures:function(request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
+if(!doc||doc.length<=0){return null;}
+return this.format.read(doc);},commit:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=[],nResponses=0;var types={};types[OpenLayers.State.INSERT]=[];types[OpenLayers.State.UPDATE]=[];types[OpenLayers.State.DELETE]=[];var feature,list,requestFeatures=[];for(var i=0,len=features.length;i<len;++i){feature=features[i];list=types[feature.state];if(list){list.push(feature);requestFeatures.push(feature);}}
+var nRequests=(types[OpenLayers.State.INSERT].length>0?1:0)+
+types[OpenLayers.State.UPDATE].length+
+types[OpenLayers.State.DELETE].length;var success=true;var finalResponse=new OpenLayers.Protocol.Response({reqFeatures:requestFeatures});function insertCallback(response){var len=response.features?response.features.length:0;var fids=new Array(len);for(var i=0;i<len;++i){fids[i]=response.features[i].fid;}
+finalResponse.insertIds=fids;callback.apply(this,[response]);}
+function callback(response){this.callUserCallback(response,options);success=success&&response.success();nResponses++;if(nResponses>=nRequests){if(options.callback){finalResponse.code=success?OpenLayers.Protocol.Response.SUCCESS:OpenLayers.Protocol.Response.FAILURE;options.callback.apply(options.scope,[finalResponse]);}}}
+var queue=types[OpenLayers.State.INSERT];if(queue.length>0){resp.push(this.create(queue,OpenLayers.Util.applyDefaults({callback:insertCallback,scope:this},options.create)));}
+queue=types[OpenLayers.State.UPDATE];for(var i=queue.length-1;i>=0;--i){resp.push(this.update(queue[i],OpenLayers.Util.applyDefaults({callback:callback,scope:this},options.update)));}
+queue=types[OpenLayers.State.DELETE];for(var i=queue.length-1;i>=0;--i){resp.push(this["delete"](queue[i],OpenLayers.Util.applyDefaults({callback:callback,scope:this},options["delete"])));}
+return resp;},abort:function(response){if(response){response.priv.abort();}},callUserCallback:function(resp,options){var opt=options[resp.requestType];if(opt&&opt.callback){opt.callback.call(opt.scope,resp);}},CLASS_NAME:"OpenLayers.Protocol.HTTP"});OpenLayers.Lang["bg"]=OpenLayers.Util.applyDefaults({'Permalink':"Постоянна препратка",'Base Layer':"Основен слой",'Scale = 1 : ${scaleDenom}':"Мащаб = 1 : ${scaleDenom}",'methodDeprecated':"Този метод е остарял и ще бъде премахват в 3.0. Вместо него използвайте ${newMethod}."});OpenLayers.Lang["hr"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nepodržani zahtjev ${statusText}",'Permalink':"Permalink",'Overlays':"Overlays",'Base Layer':"Osnovna karta",'noFID':"Ne mogu ažurirati značajku za koju ne postoji FID.",'browserNotSupported':"Vaš preglednik ne podržava vektorsko renderiranje. Trenutno podržani rendereri su: ${renderers}",'commitSuccess':"WFS Transakcija: USPJEŠNA ${response}",'commitFailed':"WFS Transakcija: NEUSPJEŠNA ${response}",'Scale = 1 : ${scaleDenom}':"Mjerilo = 1 : ${scaleDenom}",'methodDeprecated':"Ova metoda nije odobrena i biti će maknuta u 3.0. Koristite ${newMethod}."});OpenLayers.Lang["be-tarask"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Неапрацаваны вынік запыту ${statusText}",'Permalink':"Сталая спасылка",'Overlays':"Слаі",'Base Layer':"Базавы слой",'noFID':"Немагчыма абнавіць магчымасьць, для якога не існуе FID.",'browserNotSupported':"Ваш браўзэр не падтрымлівае вэктарную графіку. У цяперашні момант падтрымліваюцца: ${renderers}",'minZoomLevelError':"Уласьцівасьць minZoomLevel прызначана толькі для выкарыстаньня са слаямі вытворнымі ад FixedZoomLevels. Тое, што  гэты wfs-слой правяраецца на minZoomLevel — рэха прошлага. Але мы ня можам выдаліць гэтую магчымасьць, таму што ад яе залежаць некаторыя заснаваныя на OL дастасаваньні. Тым ня менш, праверка minZoomLevel будзе выдаленая ў вэрсіі 3.0. Калі ласка, выкарыстоўваеце замест яе ўстаноўкі мінімальнага/максымальнага памераў, як апісана тут: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-транзакцыя: ПОСЬПЕХ ${response}",'commitFailed':"WFS-транзакцыя: ПАМЫЛКА ${response}",'googleWarning':"Не атрымалася загрузіць слой Google. \x3cbr\x3e\x3cbr\x3eКаб пазбавіцца гэтага паведамленьня, выберыце новы базавы слой у сьпісе ў верхнім правым куце.\x3cbr\x3e\x3cbr\x3e Хутчэй за ўсё, прычына ў тым, што скрыпт бібліятэкі Google Maps ня быў уключаныя альбо не ўтрымлівае слушны API-ключ для Вашага сайта.\x3cbr\x3e\x3cbr\x3eРаспрацоўшчыкам: Для таго, каб даведацца як зрабіць так, каб усё працавала, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eнацісьніце тут\x3c/a\x3e",'getLayerWarning':"Немагчыма загрузіць слой ${layerType}.\x3cbr\x3e\x3cbr\x3eКаб пазбавіцца гэтага паведамленьня, выберыце новы базавы слой у сьпісе ў верхнім правым куце.\x3cbr\x3e\x3cbr\x3eХутчэй за ўсё, прычына ў тым, што скрыпт бібліятэкі ${layerLib} ня быў слушна ўключаны.\x3cbr\x3e\x3cbr\x3eРаспрацоўшчыкам: Для таго, каб даведацца як зрабіць так, каб усё працавала, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eнацісьніце тут\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Маштаб = 1 : ${scaleDenom}",'W':"З",'E':"У",'N':"Пн",'S':"Пд",'reprojectDeprecated':"Вы выкарыстоўваеце ўстаноўку \'reproject\' для слоя ${layerName}. Гэтая ўстаноўка зьяўляецца састарэлай: яна выкарыстоўвалася для падтрымкі паказу зьвестак на камэрцыйных базавых мапах, але гэта функцыя цяпер рэалізаваная ў убудаванай падтрымцы сфэрычнай праекцыі Мэркатара. Дадатковая інфармацыя ёсьць на http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Гэты мэтад састарэлы і будзе выдалены ў вэрсіі 3.0. Калі ласка, замест яго выкарыстоўвайце ${newMethod}."});OpenLayers.Lang["cs-CZ"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nezpracovaná návratová hodnota ${statusText}",'Permalink':"Trvalý odkaz",'Overlays':"Překryvné vrstvy",'Base Layer':"Podkladové vrstvy",'noFID':"Nelze aktualizovat prvek, pro který neexistuje FID.",'browserNotSupported':"Váš prohlížeč nepodporuje vykreslování vektorů. Momentálně podporované nástroje jsou::\n${renderers}",'minZoomLevelError':"Vlastnost minZoomLevel by se měla používat pouze s potomky FixedZoomLevels vrstvami. To znamená, že vrstva wfs kontroluje, zda-li minZoomLevel není zbytek z minulosti.Nelze to ovšem vyjmout bez možnosti, že bychom rozbili aplikace postavené na OL, které by na tom mohly záviset. Proto tuto vlastnost nedoporučujeme používat --  kontrola minZoomLevel bude odstraněna ve verzi 3.0. Použijte prosím raději nastavení min/max podle příkaldu popsaného na: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaction: ÚSPĚCH ${response}",'commitFailed':"WFS Transaction: CHYBA ${response}",'googleWarning':"Nepodařilo se správně načíst vrstvu Google.\x3cbr\x3e\x3cbr\x3eAbyste se zbavili této zprávy, zvolte jinou základní vrstvu v přepínači vrstev.\x3cbr\x3e\x3cbr\x3eTo se většinou stává, pokud nebyl načten skript, nebo neobsahuje správný klíč pro API pro tuto stránku.\x3cbr\x3e\x3cbr\x3eVývojáři: Pro pomoc, aby tohle fungovalo , \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eklikněte sem\x3c/a\x3e",'getLayerWarning':"The ${layerType} Layer was unable to load correctly.\x3cbr\x3e\x3cbr\x3eTo get rid of this message, select a new BaseLayer in the layer switcher in the upper-right corner.\x3cbr\x3e\x3cbr\x3eMost likely, this is because the ${layerLib} library script was either not correctly included.\x3cbr\x3e\x3cbr\x3eDevelopers: For help getting this working correctly, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclick here\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Měřítko = 1 : ${scaleDenom}",'reprojectDeprecated':"Použil jste volbu \'reproject\' ve vrstvě ${layerName}. Tato volba není doporučená: byla zde proto, aby bylo možno zobrazovat data z okomerčních serverů, ale tato funkce je nyní zajištěna pomocí podpory Spherical Mercator. Více informací naleznete na http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Tato metoda je zavržená a bude ve verzi 3.0 odstraněna. Prosím, použijte raději ${newMethod}."});OpenLayers.Lang["br"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Distro evel reked anveret ${statusText}",'Permalink':"Peurliamm",'Overlays':"Gwiskadoù",'Base Layer':"Gwiskad diazez",'noFID':"N\'haller ket hizivaat un elfenn ma n\'eus ket a niverenn-anaout (FID) eviti.",'browserNotSupported':"N\'eo ket skoret an daskor vektorel gant ho merdeer. Setu aze an daskorerioù skoret evit ar poent :\n${renderers}",'minZoomLevelError':"Ne zleer implijout ar perzh minZoomLevel nemet evit gwiskadoù FixedZoomLevels-descendent. Ar fed ma wiria ar gwiskad WHS-se hag-eñ ez eus eus minZoomLevel zo un aspadenn gozh. Koulskoude n\'omp ket evit e ziverkañ kuit da derriñ arloadoù diazezet war OL a c\'hallfe bezañ stag outañ. Setu perak eo dispredet -- Lamet kuit e vo ar gwiriañ minZoomLevel a-is er stumm 3.0. Ober gant an arventennoù bihanañ/brasañ evel deskrivet amañ e plas : http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Treuzgread WFS : MAT EO ${response}",'commitFailed':"Treuzgread WFS Transaction: C\'HWITET ${response}",'googleWarning':"N\'eus ket bet gallet kargañ ar gwiskad Google ent reizh.\x3cbr\x3e\x3cbr\x3eEvit en em zizober eus ar c\'hemenn-mañ, dibabit ur BaseLayer nevez en diuzer gwiskadoù er c\'horn dehoù el laez.\x3cbr\x3e\x3cbr\x3eSur a-walc\'h eo peogwir n\'eo ket bet ensoc\'het levraoueg Google Maps pe neuze ne glot ket an alc\'hwez API gant ho lec\'hienn.\x3cbr\x3e\x3cbr\x3eDiorroerien : Evit reizhañ an dra-se, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclick here\x3c/a\x3e",'getLayerWarning':"N\'haller ket kargañ ar gwiskad ${layerType} ent reizh.\x3cbr\x3e\x3cbr\x3eEvit en em zizober eus ar c\'hemenn-mañ, dibabit ur BaseLayer nevez en diuzer gwiskadoù er c\'horn dehoù el laez.\x3cbr\x3e\x3cbr\x3eSur a-walc\'h eo peogwir n\'eo ket bet ensoc\'het mat al levraoueg ${layerLib}.\x3cbr\x3e\x3cbr\x3eDiorroerien : Evit gouzout penaos reizhañ an dra-se, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclick here\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Skeul = 1 : ${scaleDenom}",'W':"K",'E':"R",'N':"N",'S':"S",'reprojectDeprecated':"Emaoc\'h oc\'h implijout an dibarzh \'reproject\' war ar gwiskad ${layerName}. Dispredet eo an dibarzh-mañ : bet eo hag e talveze da ziskwel roadennoù war-c\'horre kartennoù diazez kenwerzhel, un dra hag a c\'haller ober bremañ gant an arc\'hwel dre skor banndres boullek Mercator. Muioc\'h a ditouroù a c\'haller da gaout war http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Dispredet eo an daore-se ha tennet e vo kuit eus ar stumm 3.0. Grit gant ${newMethod} e plas."});OpenLayers.Control.PinchZoom=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,containerCenter:null,pinchOrigin:null,currentCenter:null,autoActivate:true,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.handler=new OpenLayers.Handler.Pinch(this,{start:this.pinchStart,move:this.pinchMove,done:this.pinchDone},this.handlerOptions);},activate:function(){var activated=OpenLayers.Control.prototype.activate.apply(this,arguments);if(activated){this.map.events.on({moveend:this.updateContainerCenter,scope:this});this.updateContainerCenter();}
+return activated;},deactivate:function(){var deactivated=OpenLayers.Control.prototype.deactivate.apply(this,arguments);if(this.map&&this.map.events){this.map.events.un({moveend:this.updateContainerCenter,scope:this});}
+return deactivated;},updateContainerCenter:function(){var container=this.map.layerContainerDiv;this.containerCenter={x:parseInt(container.style.left,10)+50,y:parseInt(container.style.top,10)+50};},pinchStart:function(evt,pinchData){this.pinchOrigin=evt.xy;this.currentCenter=evt.xy;},pinchMove:function(evt,pinchData){var scale=pinchData.scale;var containerCenter=this.containerCenter;var pinchOrigin=this.pinchOrigin;var current=evt.xy;var dx=Math.round((current.x-pinchOrigin.x)+(scale-1)*(containerCenter.x-pinchOrigin.x));var dy=Math.round((current.y-pinchOrigin.y)+(scale-1)*(containerCenter.y-pinchOrigin.y));this.applyTransform("translate("+dx+"px, "+dy+"px) scale("+scale+")");this.currentCenter=current;},applyTransform:function(transform){var style=this.map.layerContainerDiv.style;style['-webkit-transform']=transform;style['-moz-transform']=transform;},pinchDone:function(evt,start,last){this.applyTransform("");var zoom=this.map.getZoomForResolution(this.map.getResolution()/last.scale,true);if(zoom!==this.map.getZoom()||!this.currentCenter.equals(this.pinchOrigin)){var resolution=this.map.getResolutionForZoom(zoom);var location=this.map.getLonLatFromPixel(this.pinchOrigin);var zoomPixel=this.currentCenter;var size=this.map.getSize();location.lon+=resolution*((size.w/2)-zoomPixel.x);location.lat-=resolution*((size.h/2)-zoomPixel.y);this.map.div.clientWidth=this.map.div.clientWidth;this.map.setCenter(location,zoom);}},CLASS_NAME:"OpenLayers.Control.PinchZoom"});OpenLayers.Lang["io"]=OpenLayers.Util.applyDefaults({'Scale = 1 : ${scaleDenom}':"Skalo = 1 : ${scaleDenom}"});OpenLayers.Control.LayerSwitcher=OpenLayers.Class(OpenLayers.Control,{roundedCorner:false,roundedCornerColor:"darkblue",layerStates:null,layersDiv:null,baseLayersDiv:null,baseLayers:null,dataLbl:null,dataLayersDiv:null,dataLayers:null,minimizeDiv:null,maximizeDiv:null,ascending:true,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.layerStates=[];if(this.roundedCorner){OpenLayers.Console.warn('roundedCorner option is deprecated');}},destroy:function(){this.clearLayersArray("base");this.clearLayersArray("data");this.map.events.un({buttonclick:this.onButtonClick,addlayer:this.redraw,changelayer:this.redraw,removelayer:this.redraw,changebaselayer:this.redraw,scope:this});this.events.unregister("buttonclick",this,this.onButtonClick);OpenLayers.Control.prototype.destroy.apply(this,arguments);},setMap:function(map){OpenLayers.Control.prototype.setMap.apply(this,arguments);this.map.events.on({addlayer:this.redraw,changelayer:this.redraw,removelayer:this.redraw,changebaselayer:this.redraw,scope:this});if(this.outsideViewport){this.events.attachToElement(this.div);this.events.register("buttonclick",this,this.onButtonClick);}else{this.map.events.register("buttonclick",this,this.onButtonClick);}},draw:function(){OpenLayers.Control.prototype.draw.apply(this);this.loadContents();if(!this.outsideViewport){this.minimizeControl();}
+this.redraw();return this.div;},onButtonClick:function(evt){var button=evt.buttonElement;if(button===this.minimizeDiv){this.minimizeControl();}else if(button===this.maximizeDiv){this.maximizeControl();}else if(button._layerSwitcher===this.id){if(button["for"]){button=document.getElementById(button["for"]);}
+if(!button.disabled){if(button.type=="radio"){button.checked=true;this.map.setBaseLayer(this.map.getLayer(button._layer));}else{button.checked=!button.checked;this.updateMap();}}}},clearLayersArray:function(layersType){this[layersType+"LayersDiv"].innerHTML="";this[layersType+"Layers"]=[];},checkRedraw:function(){var redraw=false;if(!this.layerStates.length||(this.map.layers.length!=this.layerStates.length)){redraw=true;}else{for(var i=0,len=this.layerStates.length;i<len;i++){var layerState=this.layerStates[i];var layer=this.map.layers[i];if((layerState.name!=layer.name)||(layerState.inRange!=layer.inRange)||(layerState.id!=layer.id)||(layerState.visibility!=layer.visibility)){redraw=true;break;}}}
+return redraw;},redraw:function(){if(!this.checkRedraw()){return this.div;}
+this.clearLayersArray("base");this.clearLayersArray("data");var containsOverlays=false;var containsBaseLayers=false;var len=this.map.layers.length;this.layerStates=new Array(len);for(var i=0;i<len;i++){var layer=this.map.layers[i];this.layerStates[i]={'name':layer.name,'visibility':layer.visibility,'inRange':layer.inRange,'id':layer.id};}
+var layers=this.map.layers.slice();if(!this.ascending){layers.reverse();}
+for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];var baseLayer=layer.isBaseLayer;if(layer.displayInLayerSwitcher){if(baseLayer){containsBaseLayers=true;}else{containsOverlays=true;}
+var checked=(baseLayer)?(layer==this.map.baseLayer):layer.getVisibility();var inputElem=document.createElement("input");inputElem.id=this.id+"_input_"+layer.name;inputElem.name=(baseLayer)?this.id+"_baseLayers":layer.name;inputElem.type=(baseLayer)?"radio":"checkbox";inputElem.value=layer.name;inputElem.checked=checked;inputElem.defaultChecked=checked;inputElem.className="olButton";inputElem._layer=layer.id;inputElem._layerSwitcher=this.id;if(!baseLayer&&!layer.inRange){inputElem.disabled=true;}
+var labelSpan=document.createElement("label");labelSpan["for"]=inputElem.id;OpenLayers.Element.addClass(labelSpan,"labelSpan olButton");labelSpan._layer=layer.id;labelSpan._layerSwitcher=this.id;if(!baseLayer&&!layer.inRange){labelSpan.style.color="gray";}
+labelSpan.innerHTML=layer.name;labelSpan.style.verticalAlign=(baseLayer)?"bottom":"baseline";var br=document.createElement("br");var groupArray=(baseLayer)?this.baseLayers:this.dataLayers;groupArray.push({'layer':layer,'inputElem':inputElem,'labelSpan':labelSpan});var groupDiv=(baseLayer)?this.baseLayersDiv:this.dataLayersDiv;groupDiv.appendChild(inputElem);groupDiv.appendChild(labelSpan);groupDiv.appendChild(br);}}
+this.dataLbl.style.display=(containsOverlays)?"":"none";this.baseLbl.style.display=(containsBaseLayers)?"":"none";return this.div;},updateMap:function(){for(var i=0,len=this.baseLayers.length;i<len;i++){var layerEntry=this.baseLayers[i];if(layerEntry.inputElem.checked){this.map.setBaseLayer(layerEntry.layer,false);}}
+for(var i=0,len=this.dataLayers.length;i<len;i++){var layerEntry=this.dataLayers[i];layerEntry.layer.setVisibility(layerEntry.inputElem.checked);}},maximizeControl:function(e){this.div.style.width="";this.div.style.height="";this.showControls(false);if(e!=null){OpenLayers.Event.stop(e);}},minimizeControl:function(e){this.div.style.width="0px";this.div.style.height="0px";this.showControls(true);if(e!=null){OpenLayers.Event.stop(e);}},showControls:function(minimize){this.maximizeDiv.style.display=minimize?"":"none";this.minimizeDiv.style.display=minimize?"none":"";this.layersDiv.style.display=minimize?"none":"";},loadContents:function(){this.layersDiv=document.createElement("div");this.layersDiv.id=this.id+"_layersDiv";OpenLayers.Element.addClass(this.layersDiv,"layersDiv");this.baseLbl=document.createElement("div");this.baseLbl.innerHTML=OpenLayers.i18n("Base Layer");OpenLayers.Element.addClass(this.baseLbl,"baseLbl");this.baseLayersDiv=document.createElement("div");OpenLayers.Element.addClass(this.baseLayersDiv,"baseLayersDiv");this.dataLbl=document.createElement("div");this.dataLbl.innerHTML=OpenLayers.i18n("Overlays");OpenLayers.Element.addClass(this.dataLbl,"dataLbl");this.dataLayersDiv=document.createElement("div");OpenLayers.Element.addClass(this.dataLayersDiv,"dataLayersDiv");if(this.ascending){this.layersDiv.appendChild(this.baseLbl);this.layersDiv.appendChild(this.baseLayersDiv);this.layersDiv.appendChild(this.dataLbl);this.layersDiv.appendChild(this.dataLayersDiv);}else{this.layersDiv.appendChild(this.dataLbl);this.layersDiv.appendChild(this.dataLayersDiv);this.layersDiv.appendChild(this.baseLbl);this.layersDiv.appendChild(this.baseLayersDiv);}
+this.div.appendChild(this.layersDiv);if(this.roundedCorner){OpenLayers.Rico.Corner.round(this.div,{corners:"tl bl",bgColor:"transparent",color:this.roundedCornerColor,blend:false});OpenLayers.Rico.Corner.changeOpacity(this.layersDiv,0.75);}
+var img=OpenLayers.Util.getImageLocation('layer-switcher-maximize.png');this.maximizeDiv=OpenLayers.Util.createAlphaImageDiv("OpenLayers_Control_MaximizeDiv",null,null,img,"absolute");OpenLayers.Element.addClass(this.maximizeDiv,"maximizeDiv olButton");this.maximizeDiv.style.display="none";this.div.appendChild(this.maximizeDiv);var img=OpenLayers.Util.getImageLocation('layer-switcher-minimize.png');this.minimizeDiv=OpenLayers.Util.createAlphaImageDiv("OpenLayers_Control_MinimizeDiv",null,null,img,"absolute");OpenLayers.Element.addClass(this.minimizeDiv,"minimizeDiv olButton");this.minimizeDiv.style.display="none";this.div.appendChild(this.minimizeDiv);},CLASS_NAME:"OpenLayers.Control.LayerSwitcher"});OpenLayers.Lang["el"]=OpenLayers.Util.applyDefaults({'Scale = 1 : ${scaleDenom}':"Κλίμακα ~ 1 : ${scaleDenom}"});OpenLayers.Control.ArgParser=OpenLayers.Class(OpenLayers.Control,{center:null,zoom:null,layers:null,displayProjection:null,getParameters:function(url){url=url||window.location.href;var parameters=OpenLayers.Util.getParameters(url);var index=url.indexOf('#');if(index>0){url='?'+url.substring(index+1,url.length);OpenLayers.Util.extend(parameters,OpenLayers.Util.getParameters(url));}
+return parameters;},setMap:function(map){OpenLayers.Control.prototype.setMap.apply(this,arguments);for(var i=0,len=this.map.controls.length;i<len;i++){var control=this.map.controls[i];if((control!=this)&&(control.CLASS_NAME=="OpenLayers.Control.ArgParser")){if(control.displayProjection!=this.displayProjection){this.displayProjection=control.displayProjection;}
+break;}}
+if(i==this.map.controls.length){var args=this.getParameters();if(args.layers){this.layers=args.layers;this.map.events.register('addlayer',this,this.configureLayers);this.configureLayers();}
+if(args.lat&&args.lon){this.center=new OpenLayers.LonLat(parseFloat(args.lon),parseFloat(args.lat));if(args.zoom){this.zoom=parseFloat(args.zoom);}
+this.map.events.register('changebaselayer',this,this.setCenter);this.setCenter();}}},setCenter:function(){if(this.map.baseLayer){this.map.events.unregister('changebaselayer',this,this.setCenter);if(this.displayProjection){this.center.transform(this.displayProjection,this.map.getProjectionObject());}
+this.map.setCenter(this.center,this.zoom);}},configureLayers:function(){if(this.layers.length==this.map.layers.length){this.map.events.unregister('addlayer',this,this.configureLayers);for(var i=0,len=this.layers.length;i<len;i++){var layer=this.map.layers[i];var c=this.layers.charAt(i);if(c=="B"){this.map.setBaseLayer(layer);}else if((c=="T")||(c=="F")){layer.setVisibility(c=="T");}}}},CLASS_NAME:"OpenLayers.Control.ArgParser"});
\ No newline at end of file
diff --git a/cookbooks/web/files/default/static/openlayers/OpenStreetMap.js b/cookbooks/web/files/default/static/openlayers/OpenStreetMap.js
new file mode 100644 (file)
index 0000000..44e338b
--- /dev/null
@@ -0,0 +1,98 @@
+/**
+ * Class: OpenLayers.Layer.OSM.Mapnik
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.OSM>
+ */
+OpenLayers.Layer.OSM.Mapnik = OpenLayers.Class(OpenLayers.Layer.OSM, {
+    /**
+     * Constructor: OpenLayers.Layer.OSM.Mapnik
+     *
+     * Parameters:
+     * name - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+        var url = [
+            "https://a.tile.openstreetmap.org/${z}/${x}/${y}.png",
+            "https://b.tile.openstreetmap.org/${z}/${x}/${y}.png",
+            "https://c.tile.openstreetmap.org/${z}/${x}/${y}.png"
+        ];
+        options = OpenLayers.Util.extend({
+            numZoomLevels: 20,
+            attribution: "&copy; <a href='https://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors",
+            buffer: 0,
+            transitionEffect: "resize"
+        }, options);
+        var newArguments = [name, url, options];
+        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.OSM.Mapnik"
+});
+
+/**
+ * Class: OpenLayers.Layer.OSM.CycleMap
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.OSM>
+ */
+OpenLayers.Layer.OSM.CycleMap = OpenLayers.Class(OpenLayers.Layer.OSM, {
+    /**
+     * Constructor: OpenLayers.Layer.OSM.CycleMap
+     *
+     * Parameters:
+     * name - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+        var url = [
+            "http://a.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png",
+            "http://b.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png",
+            "http://c.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png"
+        ];
+        options = OpenLayers.Util.extend({
+            numZoomLevels: 19,
+            attribution: "&copy; <a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors, Tiles courtesy of <a href='http://www.opencyclemap.org'>Andy Allan</a>",
+            buffer: 0,
+            transitionEffect: "resize"
+        }, options);
+        var newArguments = [name, url, options];
+        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.OSM.CycleMap"
+});
+
+/**
+ * Class: OpenLayers.Layer.OSM.TransportMap
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.OSM>
+ */
+OpenLayers.Layer.OSM.TransportMap = OpenLayers.Class(OpenLayers.Layer.OSM, {
+    /**
+     * Constructor: OpenLayers.Layer.OSM.TransportMap
+     *
+     * Parameters:
+     * name - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+        var url = [
+            "http://a.tile2.opencyclemap.org/transport/${z}/${x}/${y}.png",
+            "http://b.tile2.opencyclemap.org/transport/${z}/${x}/${y}.png",
+            "http://c.tile2.opencyclemap.org/transport/${z}/${x}/${y}.png"
+        ];
+        options = OpenLayers.Util.extend({
+            numZoomLevels: 19,
+            attribution: "&copy; <a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors, Tiles courtesy of <a href='http://www.opencyclemap.org'>Andy Allan</a>",
+            buffer: 0,
+            transitionEffect: "resize"
+        }, options);
+        var newArguments = [name, url, options];
+        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.OSM.TransportMap"
+});
diff --git a/cookbooks/web/files/default/static/openlayers/img/404.png b/cookbooks/web/files/default/static/openlayers/img/404.png
new file mode 100644 (file)
index 0000000..df0f967
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/404.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/blank.gif b/cookbooks/web/files/default/static/openlayers/img/blank.gif
new file mode 100644 (file)
index 0000000..4bcc753
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/blank.gif differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/cloud-popup-relative.png b/cookbooks/web/files/default/static/openlayers/img/cloud-popup-relative.png
new file mode 100644 (file)
index 0000000..c9fd4c4
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/cloud-popup-relative.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/drag-rectangle-off.png b/cookbooks/web/files/default/static/openlayers/img/drag-rectangle-off.png
new file mode 100644 (file)
index 0000000..382a81d
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/drag-rectangle-off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/drag-rectangle-on.png b/cookbooks/web/files/default/static/openlayers/img/drag-rectangle-on.png
new file mode 100644 (file)
index 0000000..2ed2d5b
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/drag-rectangle-on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/east-mini.png b/cookbooks/web/files/default/static/openlayers/img/east-mini.png
new file mode 100644 (file)
index 0000000..ecedc5e
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/east-mini.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/layer-switcher-maximize.png b/cookbooks/web/files/default/static/openlayers/img/layer-switcher-maximize.png
new file mode 100644 (file)
index 0000000..f346086
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/layer-switcher-maximize.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/layer-switcher-minimize.png b/cookbooks/web/files/default/static/openlayers/img/layer-switcher-minimize.png
new file mode 100644 (file)
index 0000000..b4aab0b
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/layer-switcher-minimize.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/marker-blue.png b/cookbooks/web/files/default/static/openlayers/img/marker-blue.png
new file mode 100644 (file)
index 0000000..f5b4efc
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/marker-blue.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/marker-gold.png b/cookbooks/web/files/default/static/openlayers/img/marker-gold.png
new file mode 100644 (file)
index 0000000..0b62f96
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/marker-gold.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/marker-green.png b/cookbooks/web/files/default/static/openlayers/img/marker-green.png
new file mode 100644 (file)
index 0000000..c36b164
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/marker-green.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/marker.png b/cookbooks/web/files/default/static/openlayers/img/marker.png
new file mode 100644 (file)
index 0000000..ea3e59a
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/marker.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/measuring-stick-off.png b/cookbooks/web/files/default/static/openlayers/img/measuring-stick-off.png
new file mode 100644 (file)
index 0000000..efbf63f
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/measuring-stick-off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/measuring-stick-on.png b/cookbooks/web/files/default/static/openlayers/img/measuring-stick-on.png
new file mode 100644 (file)
index 0000000..2d41c84
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/measuring-stick-on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/north-mini.png b/cookbooks/web/files/default/static/openlayers/img/north-mini.png
new file mode 100644 (file)
index 0000000..dfd7211
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/north-mini.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/panning-hand-off.png b/cookbooks/web/files/default/static/openlayers/img/panning-hand-off.png
new file mode 100644 (file)
index 0000000..d1c593e
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/panning-hand-off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/panning-hand-on.png b/cookbooks/web/files/default/static/openlayers/img/panning-hand-on.png
new file mode 100644 (file)
index 0000000..9b7e064
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/panning-hand-on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/slider.png b/cookbooks/web/files/default/static/openlayers/img/slider.png
new file mode 100644 (file)
index 0000000..4335364
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/slider.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/south-mini.png b/cookbooks/web/files/default/static/openlayers/img/south-mini.png
new file mode 100644 (file)
index 0000000..2970875
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/south-mini.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/west-mini.png b/cookbooks/web/files/default/static/openlayers/img/west-mini.png
new file mode 100644 (file)
index 0000000..363cd3d
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/west-mini.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/zoom-minus-mini.png b/cookbooks/web/files/default/static/openlayers/img/zoom-minus-mini.png
new file mode 100644 (file)
index 0000000..8f0d77f
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/zoom-minus-mini.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/zoom-plus-mini.png b/cookbooks/web/files/default/static/openlayers/img/zoom-plus-mini.png
new file mode 100644 (file)
index 0000000..a73ab4e
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/zoom-plus-mini.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/zoom-world-mini.png b/cookbooks/web/files/default/static/openlayers/img/zoom-world-mini.png
new file mode 100644 (file)
index 0000000..aebf22d
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/zoom-world-mini.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/img/zoombar.png b/cookbooks/web/files/default/static/openlayers/img/zoombar.png
new file mode 100644 (file)
index 0000000..47110ab
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/img/zoombar.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/google.css b/cookbooks/web/files/default/static/openlayers/theme/default/google.css
new file mode 100644 (file)
index 0000000..3ee757c
--- /dev/null
@@ -0,0 +1,17 @@
+.olLayerGoogleCopyright {
+    right: 3px;
+    bottom: 2px;
+    left: auto;  
+}
+.olLayerGoogleV3.olLayerGoogleCopyright {
+    bottom: 0px;
+    right: 0px !important;
+}
+.olLayerGooglePoweredBy {
+    left: 2px;
+    bottom: 2px;   
+}
+.olLayerGoogleV3.olLayerGooglePoweredBy {
+    bottom: 0px !important;
+}
+
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/ie6-style.css b/cookbooks/web/files/default/static/openlayers/theme/default/ie6-style.css
new file mode 100755 (executable)
index 0000000..a0fd7c6
--- /dev/null
@@ -0,0 +1,10 @@
+.olControlZoomPanel div {
+    background-image: url(img/zoom-panel-NOALPHA.png);
+}
+.olControlPanPanel div {
+    background-image: url(img/pan-panel-NOALPHA.png);
+}
+.olControlEditingToolbar {
+    width: 200px;
+}
+
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/add_point_off.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/add_point_off.png
new file mode 100644 (file)
index 0000000..26c0233
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/add_point_off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/add_point_on.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/add_point_on.png
new file mode 100644 (file)
index 0000000..1294a2c
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/add_point_on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/blank.gif b/cookbooks/web/files/default/static/openlayers/theme/default/img/blank.gif
new file mode 100644 (file)
index 0000000..4bcc753
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/blank.gif differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/close.gif b/cookbooks/web/files/default/static/openlayers/theme/default/img/close.gif
new file mode 100644 (file)
index 0000000..a8958de
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/close.gif differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/drag-rectangle-off.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/drag-rectangle-off.png
new file mode 100644 (file)
index 0000000..382a81d
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/drag-rectangle-off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/drag-rectangle-on.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/drag-rectangle-on.png
new file mode 100644 (file)
index 0000000..2ed2d5b
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/drag-rectangle-on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_line_off.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_line_off.png
new file mode 100644 (file)
index 0000000..a4d67b3
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_line_off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_line_on.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_line_on.png
new file mode 100644 (file)
index 0000000..90dcf3e
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_line_on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_point_off.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_point_off.png
new file mode 100644 (file)
index 0000000..5633407
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_point_off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_point_on.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_point_on.png
new file mode 100644 (file)
index 0000000..fff50b7
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_point_on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_polygon_off.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_polygon_off.png
new file mode 100644 (file)
index 0000000..917af35
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_polygon_off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_polygon_on.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_polygon_on.png
new file mode 100644 (file)
index 0000000..05a2cc5
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/draw_polygon_on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/editing_tool_bar.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/editing_tool_bar.png
new file mode 100644 (file)
index 0000000..5977856
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/editing_tool_bar.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/move_feature_off.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/move_feature_off.png
new file mode 100644 (file)
index 0000000..ed4472d
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/move_feature_off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/move_feature_on.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/move_feature_on.png
new file mode 100644 (file)
index 0000000..62226a2
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/move_feature_on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/navigation_history.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/navigation_history.png
new file mode 100644 (file)
index 0000000..84e3489
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/navigation_history.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/overview_replacement.gif b/cookbooks/web/files/default/static/openlayers/theme/default/img/overview_replacement.gif
new file mode 100644 (file)
index 0000000..a82cf5f
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/overview_replacement.gif differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/pan-panel-NOALPHA.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/pan-panel-NOALPHA.png
new file mode 100644 (file)
index 0000000..6987268
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/pan-panel-NOALPHA.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/pan-panel.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/pan-panel.png
new file mode 100644 (file)
index 0000000..dfe6748
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/pan-panel.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/pan_off.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/pan_off.png
new file mode 100644 (file)
index 0000000..30b2aed
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/pan_off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/pan_on.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/pan_on.png
new file mode 100644 (file)
index 0000000..e3953a8
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/pan_on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/panning-hand-off.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/panning-hand-off.png
new file mode 100644 (file)
index 0000000..d1c593e
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/panning-hand-off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/panning-hand-on.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/panning-hand-on.png
new file mode 100644 (file)
index 0000000..9b7e064
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/panning-hand-on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/remove_point_off.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/remove_point_off.png
new file mode 100644 (file)
index 0000000..76c8606
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/remove_point_off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/remove_point_on.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/remove_point_on.png
new file mode 100644 (file)
index 0000000..cc8d7b2
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/remove_point_on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/ruler.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/ruler.png
new file mode 100644 (file)
index 0000000..aa4883b
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/ruler.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/save_features_off.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/save_features_off.png
new file mode 100644 (file)
index 0000000..3d305b6
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/save_features_off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/save_features_on.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/save_features_on.png
new file mode 100644 (file)
index 0000000..5640ae8
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/save_features_on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/view_next_off.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/view_next_off.png
new file mode 100644 (file)
index 0000000..9149a24
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/view_next_off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/view_next_on.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/view_next_on.png
new file mode 100644 (file)
index 0000000..e41fb7b
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/view_next_on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/view_previous_off.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/view_previous_off.png
new file mode 100644 (file)
index 0000000..8a9ef21
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/view_previous_off.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/view_previous_on.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/view_previous_on.png
new file mode 100644 (file)
index 0000000..c009c25
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/view_previous_on.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/zoom-panel-NOALPHA.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/zoom-panel-NOALPHA.png
new file mode 100644 (file)
index 0000000..cdde6fc
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/zoom-panel-NOALPHA.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/img/zoom-panel.png b/cookbooks/web/files/default/static/openlayers/theme/default/img/zoom-panel.png
new file mode 100644 (file)
index 0000000..c91a4ef
Binary files /dev/null and b/cookbooks/web/files/default/static/openlayers/theme/default/img/zoom-panel.png differ
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/style.css b/cookbooks/web/files/default/static/openlayers/theme/default/style.css
new file mode 100644 (file)
index 0000000..8e0abb7
--- /dev/null
@@ -0,0 +1,484 @@
+div.olMap {
+    z-index: 0;
+    padding: 0 !important;
+    margin: 0 !important;
+    cursor: default;
+}
+
+div.olMapViewport {
+    text-align: left;
+}
+
+div.olLayerDiv {
+   -moz-user-select: none;
+   -khtml-user-select: none;
+}
+
+.olLayerGoogleCopyright {
+    left: 2px;
+    bottom: 2px;
+}
+.olLayerGoogleV3.olLayerGoogleCopyright {
+    right: auto !important;
+}
+.olLayerGooglePoweredBy {
+    left: 2px;
+    bottom: 15px;
+}
+.olLayerGoogleV3.olLayerGooglePoweredBy {
+    bottom: 15px !important;
+}
+.olControlAttribution {
+    font-size: smaller;
+    right: 3px;
+    bottom: 4.5em;
+    position: absolute;
+    display: block;
+}
+.olControlScale {
+    right: 3px;
+    bottom: 3em;
+    display: block;
+    position: absolute;
+    font-size: smaller;
+}
+.olControlScaleLine {
+   display: block;
+   position: absolute;
+   left: 10px;
+   bottom: 15px;
+   font-size: xx-small;
+}
+.olControlScaleLineBottom {
+   border: solid 2px black;
+   border-bottom: none;
+   margin-top:-2px;
+   text-align: center;
+}
+.olControlScaleLineTop {
+   border: solid 2px black;
+   border-top: none;
+   text-align: center;
+}
+
+.olControlPermalink {
+    right: 3px;
+    bottom: 1.5em;
+    display: block;
+    position: absolute;
+    font-size: smaller;
+}
+
+div.olControlMousePosition {
+    bottom: 0;
+    right: 3px;
+    display: block;
+    position: absolute;
+    font-family: Arial;
+    font-size: smaller;
+}
+
+.olControlOverviewMapContainer {
+    position: absolute;
+    bottom: 0;
+    right: 0;
+}
+
+.olControlOverviewMapElement {
+    padding: 10px 18px 10px 10px;
+    background-color: #00008B;
+    -moz-border-radius: 1em 0 0 0;
+}
+
+.olControlOverviewMapMinimizeButton,
+.olControlOverviewMapMaximizeButton {
+    height: 18px;
+    width: 18px;
+    right: 0;
+    bottom: 80px;
+    cursor: pointer;
+}
+
+.olControlOverviewMapExtentRectangle {
+    overflow: hidden;
+    background-image: url("img/blank.gif");
+    cursor: move;
+    border: 2px dotted red;
+}
+.olControlOverviewMapRectReplacement {
+    overflow: hidden;
+    cursor: move;
+    background-image: url("img/overview_replacement.gif");
+    background-repeat: no-repeat;
+    background-position: center;
+}
+
+.olLayerGeoRSSDescription {
+    float:left;
+    width:100%;
+    overflow:auto;
+    font-size:1.0em;
+}
+.olLayerGeoRSSClose {
+    float:right;
+    color:gray;
+    font-size:1.2em;
+    margin-right:6px;
+    font-family:sans-serif;
+}
+.olLayerGeoRSSTitle {
+    float:left;font-size:1.2em;
+}
+
+.olPopupContent {
+    padding:5px;
+    overflow: auto;
+}
+
+.olControlNavigationHistory {
+   background-image: url("img/navigation_history.png");
+   background-repeat: no-repeat;
+   width:  24px;
+   height: 24px;
+
+}
+.olControlNavigationHistoryPreviousItemActive {
+  background-position: 0 0;
+}
+.olControlNavigationHistoryPreviousItemInactive {
+   background-position: 0 -24px;
+}
+.olControlNavigationHistoryNextItemActive {
+   background-position: -24px 0;
+}
+.olControlNavigationHistoryNextItemInactive {
+   background-position: -24px -24px;
+}
+
+div.olControlSaveFeaturesItemActive {
+    background-image: url(img/save_features_on.png);
+    background-repeat: no-repeat;
+    background-position: 0 1px;
+}
+div.olControlSaveFeaturesItemInactive {
+    background-image: url(img/save_features_off.png);
+    background-repeat: no-repeat;
+    background-position: 0 1px;
+}
+
+.olHandlerBoxZoomBox {
+    border: 2px solid red;
+    position: absolute;
+    background-color: white;
+    opacity: 0.50;
+    font-size: 1px;
+    filter: alpha(opacity=50);
+}
+.olHandlerBoxSelectFeature {
+    border: 2px solid blue;
+    position: absolute;
+    background-color: white;
+    opacity: 0.50;
+    font-size: 1px;
+    filter: alpha(opacity=50);
+}
+
+.olControlPanPanel {
+    top: 10px;
+    left: 5px;
+}
+
+.olControlPanPanel div {
+    background-image: url(img/pan-panel.png);
+    height: 18px;
+    width: 18px;
+    cursor: pointer;
+    position: absolute;
+}
+
+.olControlPanPanel .olControlPanNorthItemInactive {
+    top: 0;
+    left: 9px;
+    background-position: 0 0;
+}
+.olControlPanPanel .olControlPanSouthItemInactive {
+    top: 36px;
+    left: 9px;
+    background-position: 18px 0;
+}
+.olControlPanPanel .olControlPanWestItemInactive {
+    position: absolute;
+    top: 18px;
+    left: 0;
+    background-position: 0 18px;
+}
+.olControlPanPanel .olControlPanEastItemInactive {
+    top: 18px;
+    left: 18px;
+    background-position: 18px 18px;
+}
+
+.olControlZoomPanel {
+    top: 71px;
+    left: 14px;
+}
+
+.olControlZoomPanel div {
+    background-image: url(img/zoom-panel.png);
+    position: absolute;
+    height: 18px;
+    width: 18px;
+    cursor: pointer;
+}
+
+.olControlZoomPanel .olControlZoomInItemInactive {
+    top: 0;
+    left: 0;
+    background-position: 0 0;
+}
+
+.olControlZoomPanel .olControlZoomToMaxExtentItemInactive {
+    top: 18px;
+    left: 0;
+    background-position: 0 -18px;
+}
+
+.olControlZoomPanel .olControlZoomOutItemInactive {
+    top: 36px;
+    left: 0;
+    background-position: 0 18px;
+}
+
+/*
+ * When a potential text is bigger than the image it move the image
+ * with some headers (closes #3154)
+ */
+.olControlPanZoomBar div {
+    font-size: 1px;
+}
+
+.olPopupCloseBox {
+  background: url("img/close.gif") no-repeat;
+  cursor: pointer;
+}
+
+.olFramedCloudPopupContent {
+    padding: 5px;
+    overflow: auto;
+}
+
+.olControlNoSelect {
+ -moz-user-select: none;
+ -khtml-user-select: none;
+}
+
+.olImageLoadError {
+    background-color: pink;
+    opacity: 0.5;
+    filter: alpha(opacity=50); /* IE */
+}
+
+/**
+ * Cursor styles
+ */
+
+.olCursorWait {
+    cursor: wait;
+}
+.olDragDown {
+    cursor: move;
+}
+.olDrawBox {
+    cursor: crosshair;
+}
+.olControlDragFeatureOver {
+    cursor: move;
+}
+.olControlDragFeatureActive.olControlDragFeatureOver.olDragDown {
+    cursor: -moz-grabbing;
+}
+
+/**
+ * Layer switcher
+ */
+.olControlLayerSwitcher {
+    position: absolute;
+    top: 25px;
+    right: 0;
+    width: 20em;
+    font-family: sans-serif;
+    font-weight: bold;
+    margin-top: 3px;
+    margin-left: 3px;
+    margin-bottom: 3px;
+    font-size: smaller;
+    color: white;
+    background-color: transparent;
+}
+
+.olControlLayerSwitcher .layersDiv {
+    padding-top: 5px;
+    padding-left: 10px;
+    padding-bottom: 5px;
+    padding-right: 10px;
+    background-color: darkblue;
+}
+
+.olControlLayerSwitcher .layersDiv .baseLbl,
+.olControlLayerSwitcher .layersDiv .dataLbl {
+    margin-top: 3px;
+    margin-left: 3px;
+    margin-bottom: 3px;
+}
+
+.olControlLayerSwitcher .layersDiv .baseLayersDiv,
+.olControlLayerSwitcher .layersDiv .dataLayersDiv {
+    padding-left: 10px;
+}
+
+.olControlLayerSwitcher .maximizeDiv,
+.olControlLayerSwitcher .minimizeDiv {
+    width: 18px;
+    height: 18px;
+    top: 5px;
+    right: 0;
+    cursor: pointer;
+}
+
+.olBingAttribution {
+    color: #DDD;
+}
+.olBingAttribution.road {
+    color: #333;
+}
+
+.olGoogleAttribution.hybrid, .olGoogleAttribution.satellite {
+    color: #EEE;
+}
+.olGoogleAttribution {
+    color: #333;
+}
+span.olGoogleAttribution a {
+    color: #77C;
+}
+span.olGoogleAttribution.hybrid a, span.olGoogleAttribution.satellite a {
+    color: #EEE;
+}
+
+/**
+ * Editing and navigation icons.
+ * (using the editing_tool_bar.png sprint image)
+ */
+.olControlNavToolbar ,
+.olControlEditingToolbar {
+    margin: 5px 5px 0 0;
+}
+.olControlNavToolbar div,
+.olControlEditingToolbar div {
+    background-image: url("img/editing_tool_bar.png");
+    background-repeat: no-repeat;
+    margin: 0 0 5px 5px;
+    width: 24px;
+    height: 22px;
+    cursor: pointer
+}
+/* positions */
+.olControlEditingToolbar {
+    right: 0;
+    top: 0;
+}
+.olControlNavToolbar {
+    top: 295px;
+    left: 9px;
+}
+/* layouts */
+.olControlEditingToolbar div {
+    float: right;
+}
+/* individual controls */
+.olControlNavToolbar .olControlNavigationItemInactive,
+.olControlEditingToolbar .olControlNavigationItemInactive {
+    background-position: -103px -1px;
+}
+.olControlNavToolbar .olControlNavigationItemActive ,
+.olControlEditingToolbar .olControlNavigationItemActive  {
+    background-position: -103px -24px;
+}
+.olControlNavToolbar .olControlZoomBoxItemInactive {
+    background-position: -128px -1px;
+}
+.olControlNavToolbar .olControlZoomBoxItemActive  {
+    background-position: -128px -24px;
+}
+.olControlEditingToolbar .olControlDrawFeaturePointItemInactive {
+    background-position: -77px -1px;
+}
+.olControlEditingToolbar .olControlDrawFeaturePointItemActive {
+    background-position: -77px -24px;
+}
+.olControlEditingToolbar .olControlDrawFeaturePathItemInactive {
+    background-position: -51px -1px;
+}
+.olControlEditingToolbar .olControlDrawFeaturePathItemActive {
+    background-position: -51px -24px;
+}
+.olControlEditingToolbar .olControlDrawFeaturePolygonItemInactive{
+    background-position: -26px -1px;
+}
+.olControlEditingToolbar .olControlDrawFeaturePolygonItemActive {
+    background-position: -26px -24px;
+}
+
+div.olControlZoom {
+    position: absolute;
+    top: 8px;
+    left: 8px;
+    background: rgba(255,255,255,0.4);
+    border-radius: 4px;
+    padding: 2px;
+}
+div.olControlZoom a {
+    display: block;
+    margin: 1px;
+    padding: 0;
+    color: white;
+    font-size: 18px;
+    font-family: 'Lucida Grande', Verdana, Geneva, Lucida, Arial, Helvetica, sans-serif;
+    font-weight: bold;
+    text-decoration: none;
+    text-align: center;
+    height: 22px;
+    width:22px;
+    line-height: 19px;
+    background: #130085; /* fallback for IE - IE6 requires background shorthand*/
+    background: rgba(0, 60, 136, 0.5);
+    filter: alpha(opacity=80);
+}
+div.olControlZoom a:hover {
+    background: #130085; /* fallback for IE */
+    background: rgba(0, 60, 136, 0.7);
+    filter: alpha(opacity=100);
+}
+@media only screen and (max-width: 600px) {
+    div.olControlZoom a:hover {
+        background: rgba(0, 60, 136, 0.5);
+    }
+}
+a.olControlZoomIn {
+    border-radius: 4px 4px 0 0;
+}
+a.olControlZoomOut {
+    border-radius: 0 0 4px 4px;
+}
+
+
+/**
+ * Animations
+ */
+
+.olLayerGrid .olTileImage {
+    -webkit-transition: opacity 0.2s linear;
+    -moz-transition: opacity 0.2s linear;
+    -o-transition: opacity 0.2s linear;
+    transition: opacity 0.2s linear;
+}
diff --git a/cookbooks/web/files/default/static/openlayers/theme/default/style.mobile.css b/cookbooks/web/files/default/static/openlayers/theme/default/style.mobile.css
new file mode 100644 (file)
index 0000000..2d4d392
--- /dev/null
@@ -0,0 +1,63 @@
+div.olControlZoom {
+    position: absolute;
+    top: 8px;
+    left: 8px;
+    background: rgba(255,255,255,0.4);
+    border-radius: 4px;
+    padding: 2px;
+}
+* {
+    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+div.olControlZoom a {
+    display: block;
+    margin: 1px;
+    padding: 0;
+    color: white;
+    font-size: 28px;
+    font-family: sans-serif;
+    font-weight: bold;
+    text-decoration: none;
+    text-align: center;
+    height: 32px;
+    width: 32px;
+    line-height: 28px;
+    text-shadow: 0 0 3px rgba(0,0,0,0.8);
+    background: #130085; /* fallback for IE - IE6 requires background shorthand*/
+    background: rgba(0, 60, 136, 0.5);
+    filter: alpha(opacity=80);
+}
+a.olControlZoomIn {
+    border-radius: 4px 4px 0 0;
+}
+a.olControlZoomOut {
+    border-radius: 0 0 4px 4px;
+}
+div.olControlZoom a:hover {
+    background: #130085; /* fallback for IE */
+    background: rgba(0, 60, 136, 0.7);
+    filter: alpha(opacity=100);
+}
+@media only screen and (max-width: 600px) {
+    div.olControlZoom a:hover {
+        background: rgba(0, 60, 136, 0.5);
+    }
+}
+.olLayerGrid .olTileImage {
+    -webkit-transition: opacity 0.2s linear;
+    -moz-transition: opacity 0.2s linear;
+    -o-transition: opacity 0.2s linear;
+    transition: opacity 0.2s linear;
+}
+/* Enable 3d acceleration when operating on tiles, this is
+   known to yield better performance on IOS Safari.
+   http://osgeo-org.1803224.n2.nabble.com/Harware-accelerated-CSS3-animations-for-iOS-td6255560.html
+
+   It also prevents tile blinking effects in iOS 5.
+   See https://github.com/openlayers/openlayers/issues/511
+*/
+@media (-webkit-transform-3d) {
+img.olTileImage {
+    -webkit-transform: translate3d(0, 0, 0);
+}
+}
index 47b0dd678fe1bcb01968a26ae5f70938d63e3896..89feed9a8996a4063cdb1129cab5593b761f39a2 100644 (file)
@@ -6,13 +6,16 @@ description       "Installs and configures www.openstreetmap.org servers"
 
 version           "1.0.1"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
-depends           "passenger"
+depends           "apt"
+depends           "chef"
+depends           "geoipupdate"
 depends           "git"
 depends           "memcached"
-depends           "nodejs"
-depends           "tools"
+depends           "munin"
 depends           "nfs"
-depends           "accounts"
-depends           "apt"
+depends           "nodejs"
+depends           "passenger"
 depends           "systemd"
+depends           "tools"
index 97bab57c70ff57b294a305d1b2495ce5434a57f6..871f692d955be5794c3d30a194108e2e24d36bb0 100644 (file)
@@ -17,6 +17,8 @@
 # limitations under the License.
 #
 
+node.default[:memcached][:ip_address] = node.internal_ipaddress
+
 include_recipe "memcached"
 include_recipe "apache"
 include_recipe "web::rails"
@@ -40,20 +42,10 @@ apache_site "www.openstreetmap.org" do
             :secret_key_base => web_passwords["secret_key_base"]
 end
 
-node.normal[:memcached][:ip_address] = node.internal_ipaddress
-
 service "rails-jobs@storage" do
-  action [:enable, :start]
-  supports :restart => true
-  subscribes :restart, "rails_port[www.openstreetmap.org]"
-  subscribes :restart, "systemd_service[rails-jobs]"
+  action [:disable, :stop]
 end
 
-if node[:web][:primary_cluster]
-  service "rails-jobs@traces" do
-    action [:enable, :start]
-    supports :restart => true
-    subscribes :restart, "rails_port[www.openstreetmap.org]"
-    subscribes :restart, "systemd_service[rails-jobs]"
-  end
+service "rails-jobs@traces" do
+  action [:disable, :stop]
 end
index 00f77af6cae7525a4d5fa283ab2f07b22652f33a..2c943c6246f8e949c27d1465cb4039188ee2276a 100644 (file)
@@ -22,11 +22,12 @@ node.default[:nfs]["/store/rails"] = {
   :path => "/store/rails"
 }
 
+include_recipe "accounts"
 include_recipe "nfs"
 
 directory node[:web][:base_directory] do
   group "rails"
-  mode 0o2775
+  mode "2775"
 end
 
 systemd_tmpfile node[:web][:pid_directory] do
@@ -39,12 +40,12 @@ end
 directory node[:web][:log_directory] do
   owner "rails"
   group "rails"
-  mode 0o775
+  mode "775"
 end
 
 template "/etc/logrotate.d/web" do
   source "logrotate.web.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
index 22d6d02f0f21fb8af090311b85d6204c4861d8cb..3936c8500f169e6874b582e2f8193378047c6357 100644 (file)
@@ -17,6 +17,7 @@
 # limitations under the License.
 #
 
+include_recipe "apt"
 include_recipe "tools"
 include_recipe "web::base"
 
@@ -26,34 +27,34 @@ package "openstreetmap-cgimap-bin" do
   action :upgrade
 end
 
-if node[:web][:readonly_database_host]
-  database_host = node[:web][:readonly_database_host]
-  database_readonly = true
-else
-  database_host = node[:web][:database_host]
-  database_readonly = node[:web][:status] == "database_readonly"
-end
+database_host = node[:web][:readonly_database_host] || node[:web][:database_host]
 
 memcached_servers = node[:web][:memcached_servers] || []
 
-switches = database_readonly ? " --readonly" : ""
+cgimap_options = {
+  "CGIMAP_HOST" => database_host,
+  "CGIMAP_DBNAME" => "openstreetmap",
+  "CGIMAP_USERNAME" => "cgimap",
+  "CGIMAP_PASSWORD" => db_passwords["cgimap"],
+  "CGIMAP_OAUTH_HOST" => node[:web][:database_host],
+  "CGIMAP_UPDATE_HOST" => node[:web][:database_host],
+  "CGIMAP_PIDFILE" => "#{node[:web][:pid_directory]}/cgimap.pid",
+  "CGIMAP_LOGFILE" => "#{node[:web][:log_directory]}/cgimap.log",
+  "CGIMAP_MEMCACHE" => memcached_servers.join(","),
+  "CGIMAP_RATELIMIT" => "204800",
+  "CGIMAP_MAXDEBT" => "250"
+}
+
+if %w[database_readonly api_readonly].include?(node[:web][:status])
+  cgimap_options["CGIMAP_DISABLE_API_WRITE"] = "true"
+end
 
 systemd_service "cgimap" do
   description "OpenStreetMap API Server"
   type "forking"
-  environment_file "CGIMAP_HOST" => database_host,
-                   "CGIMAP_DBNAME" => "openstreetmap",
-                   "CGIMAP_USERNAME" => "cgimap",
-                   "CGIMAP_PASSWORD" => db_passwords["cgimap"],
-                   "CGIMAP_OAUTH_HOST" => node[:web][:database_host],
-                   "CGIMAP_UPDATE_HOST" => node[:web][:database_host],
-                   "CGIMAP_PIDFILE" => "#{node[:web][:pid_directory]}/cgimap.pid",
-                   "CGIMAP_LOGFILE" => "#{node[:web][:log_directory]}/cgimap.log",
-                   "CGIMAP_MEMCACHE" => memcached_servers.join(","),
-                   "CGIMAP_RATELIMIT" => "204800",
-                   "CGIMAP_MAXDEBT" => "250"
+  environment_file cgimap_options
   user "rails"
-  exec_start "/usr/bin/openstreetmap-cgimap --daemon --port 8000 --instances 30#{switches}"
+  exec_start "/usr/bin/openstreetmap-cgimap --daemon --port 8000 --instances 30"
   exec_reload "/bin/kill -HUP $MAINPID"
   private_tmp true
   private_devices true
index 7c3240152b779e079280a6d87f6ad7a15417d4bf..91780994f57f867c212eb3978b01aaa39440a878 100644 (file)
@@ -26,6 +26,6 @@ template "/etc/cron.daily/web-cleanup" do
   source "cleanup.cron.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   variables :ruby => ruby, :directory => rails_directory
 end
index 947b7583b1a38b5781e123e778416fcba3dd60c8..ecfaea7efb55de325f3e986e1d275b225b1576d4 100644 (file)
 # limitations under the License.
 #
 
+node.default[:memcached][:ip_address] = node.internal_ipaddress || "127.0.0.1"
+
+include_recipe "memcached"
 include_recipe "apache"
 include_recipe "web::rails"
+include_recipe "web::cgimap"
 
 web_passwords = data_bag_item("web", "passwords")
 
 apache_module "alias"
 apache_module "expires"
 apache_module "headers"
-apache_module "proxy_http"
-apache_module "proxy_balancer"
+apache_module "proxy"
+apache_module "proxy_fcgi"
 apache_module "lbmethod_byrequests"
 apache_module "lbmethod_bybusyness"
 apache_module "rewrite"
@@ -36,6 +40,16 @@ apache_site "default" do
   action [:disable]
 end
 
+remote_directory "#{node[:web][:base_directory]}/static" do
+  source "static"
+  owner "root"
+  group "root"
+  mode "755"
+  files_owner "root"
+  files_group "root"
+  files_mode "644"
+end
+
 apache_site "www.openstreetmap.org" do
   template "apache.frontend.erb"
   variables :status => node[:web][:status],
@@ -46,7 +60,7 @@ template "/etc/logrotate.d/apache2" do
   source "logrotate.apache.erb"
   owner "root"
   group "root"
-  mode 0o644
+  mode "644"
 end
 
 service "rails-jobs@mailers" do
@@ -55,3 +69,23 @@ service "rails-jobs@mailers" do
   subscribes :restart, "rails_port[www.openstreetmap.org]"
   subscribes :restart, "systemd_service[rails-jobs]"
 end
+
+service "rails-jobs@storage" do
+  action [:enable, :start]
+  supports :restart => true
+  subscribes :restart, "rails_port[www.openstreetmap.org]"
+  subscribes :restart, "systemd_service[rails-jobs]"
+end
+
+if node[:web][:primary_cluster]
+  service "rails-jobs@traces" do
+    action [:enable, :start]
+    supports :restart => true
+    subscribes :restart, "rails_port[www.openstreetmap.org]"
+    subscribes :restart, "systemd_service[rails-jobs]"
+  end
+else
+  service "rails-jobs@traces" do
+    action [:disable, :stop]
+  end
+end
index d46c09ee126c9a78d167d0a5ee031292fea2c568..caf20279f1dc8727a3847ccdfe0e245e6dd8ad1d 100644 (file)
 # limitations under the License.
 #
 
-include_recipe "tools"
-include_recipe "web::base"
-
 include_recipe "apache"
-include_recipe "passenger"
+include_recipe "apt"
 include_recipe "git"
+include_recipe "geoipupdate"
+include_recipe "munin"
 include_recipe "nodejs"
+include_recipe "passenger"
+include_recipe "tools"
+include_recipe "web::base"
 
 web_passwords = data_bag_item("web", "passwords")
 db_passwords = data_bag_item("db", "passwords")
@@ -44,7 +46,7 @@ template "/etc/cron.hourly/passenger" do
   source "passenger.cron.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 ruby_version = node[:passenger][:ruby_version]
@@ -113,13 +115,25 @@ rails_port "www.openstreetmap.org" do
   storage_url "https://openstreetmap-user-avatars.s3.dualstack.eu-west-1.amazonaws.com"
 end
 
+gem_package "bundler#{ruby_version}" do
+  package_name "bundler"
+  gem_binary "gem#{ruby_version}"
+  options "--format-executable"
+end
+
+bundle = if File.exist?("/usr/bin/bundle#{ruby_version}")
+           "/usr/bin/bundle#{ruby_version}"
+         else
+           "/usr/local/bin/bundle#{ruby_version}"
+         end
+
 systemd_service "rails-jobs@" do
   description "Rails job queue runner"
   type "simple"
   environment "RAILS_ENV" => "production", "QUEUE" => "%I"
   user "rails"
   working_directory rails_directory
-  exec_start "/usr/local/bin/bundle#{ruby_version} exec rake jobs:work"
+  exec_start "#{bundle} exec rake jobs:work"
   restart "on-failure"
   private_tmp true
   private_devices true
@@ -134,7 +148,7 @@ template "/usr/local/bin/cleanup-rails-assets" do
   source "cleanup-assets.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 gem_package "apachelogregex"
@@ -144,7 +158,7 @@ template "/usr/local/bin/api-statistics" do
   source "api-statistics.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
 end
 
 systemd_service "api-statistics" do
index c2f7d9b147ea8fa13ee8590bf3d01f509dc6685a..7f408ed79c3bd64fcc9f1cb12bcc058b6d0eabdf 100644 (file)
@@ -26,13 +26,13 @@ template "/usr/local/bin/statistics" do
   source "statistics.erb"
   owner "root"
   group "root"
-  mode 0o755
+  mode "755"
   variables :ruby => ruby, :directory => rails_directory
 end
 
-template "/etc/cron.d/statistics" do
-  source "statistics.cron.erb"
-  owner "root"
-  group "root"
-  mode 0o644
+cron_d "statistics" do
+  minute "0"
+  hour "0"
+  user "rails"
+  command "/usr/local/bin/statistics"
 end
index 0a37afe89f7ec5cc143d6c640da3d107d6505096..90028e9f9833a272b12873b3bf4031443bf26a12 100644 (file)
 require "yaml"
 
 resource_name :rails_port
+provides :rails_port
 
 default_action :create
 
-property :site, String, :name_attribute => true
+property :site, String, :name_property => true
 property :ruby, String, :default => "2.3"
 property :directory, String
 property :user, String
 property :group, String
 property :repository, String, :default => "https://git.openstreetmap.org/public/rails.git"
 property :revision, String, :default => "live"
-property :run_migrations, [TrueClass, FalseClass], :default => false
+property :run_migrations, [true, false], :default => false
+property :build_assets, [true, false], :default => true
 property :email_from, String, :default => "OpenStreetMap <support@openstreetmap.org>"
 property :status, String, :default => "online"
 property :database_host, String
@@ -63,14 +65,15 @@ property :wikipedia_auth_id, String
 property :wikipedia_auth_secret, String
 property :thunderforest_key, String
 property :totp_key, String
-property :csp_enforce, [TrueClass, FalseClass], :default => false
+property :csp_enforce, [true, false], :default => false
 property :csp_report_url, String
 property :piwik_configuration, Hash
-property :trace_use_job_queue, [TrueClass, FalseClass], :default => false
+property :trace_use_job_queue, [true, false], :default => false
 property :diary_feed_delay, Integer
 property :storage_configuration, Hash, :default => {}
 property :storage_service, String, :default => "local"
 property :storage_url, String
+property :tile_cdn_url, String
 
 action :create do
   package %W[
@@ -78,11 +81,12 @@ action :create do
     ruby#{new_resource.ruby}-dev
     imagemagick
     nodejs
-    geoip-database
+    tzdata
   ]
 
   package %w[
     g++
+    make
     pkg-config
     libpq-dev
     libsasl2-dev
@@ -108,7 +112,7 @@ action :create do
 
   gem_package "bundler#{new_resource.ruby}" do
     package_name "bundler"
-    version "1.16.2"
+    version "2.1.4"
     gem_binary "gem#{new_resource.ruby}"
     options "--format-executable"
   end
@@ -121,19 +125,16 @@ action :create do
   declare_resource :directory, rails_directory do
     owner new_resource.user
     group new_resource.group
-    mode 0o2775
+    mode "2775"
   end
 
   git rails_directory do
     action :sync
     repository new_resource.repository
     revision new_resource.revision
+    depth 1
     user new_resource.user
     group new_resource.group
-    notifies :run, "execute[#{rails_directory}/Gemfile]"
-    notifies :run, "execute[#{rails_directory}/app/assets/javascripts/i18n]"
-    notifies :run, "execute[#{rails_directory}/public/assets]"
-    notifies :delete, "file[#{rails_directory}/public/export/embed.html]"
     notifies :restart, "passenger_application[#{rails_directory}]"
   end
 
@@ -152,7 +153,7 @@ action :create do
     source "database.yml.erb"
     owner new_resource.user
     group new_resource.group
-    mode 0o664
+    mode "664"
     variables :host => new_resource.database_host,
               :port => new_resource.database_port,
               :name => new_resource.database_name,
@@ -181,7 +182,7 @@ action :create do
 
     line.gsub!(/^( *)#geonames_username:.*$/, "\\1geonames_username: \"openstreetmap\"")
 
-    line.gsub!(/^( *)#geoip_database:.*$/, "\\1geoip_database: \"/usr/share/GeoIP/GeoIPv6.dat\"")
+    line.gsub!(/^( *)#maxmind_database:.*$/, "\\1maxmind_database: \"/usr/share/GeoIP/GeoLite2-Country.mmdb\"")
 
     if new_resource.gpx_dir
       line.gsub!(/^( *)gpx_trace_dir:.*$/, "\\1gpx_trace_dir: \"#{new_resource.gpx_dir}/traces\"")
@@ -277,9 +278,9 @@ action :create do
     path "#{rails_directory}/config/application.yml"
     owner new_resource.user
     group new_resource.group
-    mode 0o664
+    mode "664"
     content application_yml
-    notifies :run, "execute[#{rails_directory}/public/assets]"
+    notifies :restart, "passenger_application[#{rails_directory}]"
     only_if { ::File.exist?("#{rails_directory}/config/example.application.yml") }
   end
 
@@ -319,14 +320,15 @@ action :create do
     "trace_use_job_queue",
     "diary_feed_delay",
     "storage_service",
-    "storage_url"
-  ).reject { |_k, v| v.nil? }.merge(
+    "storage_url",
+    "tile_cdn_url"
+  ).compact.merge(
     "server_protocol" => "https",
     "server_url" => new_resource.site,
     "support_email" => "support@openstreetmap.org",
     "email_return_path" => "bounces@openstreetmap.org",
     "geonames_username" => "openstreetmap",
-    "geoip_database" => "/usr/share/GeoIP/GeoIPv6.dat"
+    "maxmind_database" => "/usr/share/GeoIP/GeoLite2-Country.mmdb"
   )
 
   if new_resource.memcache_servers
@@ -341,9 +343,8 @@ action :create do
   file "#{rails_directory}/config/settings.local.yml" do
     owner new_resource.user
     group new_resource.group
-    mode 0o664
+    mode "664"
     content YAML.dump(settings)
-    notifies :run, "execute[#{rails_directory}/public/assets]"
     only_if { ::File.exist?("#{rails_directory}/config/settings.yml") }
   end
 
@@ -357,23 +358,20 @@ action :create do
   file "#{rails_directory}/config/storage.yml" do
     owner new_resource.user
     group new_resource.group
-    mode 0o664
+    mode "664"
     content YAML.dump(storage_configuration)
-    notifies :run, "execute[#{rails_directory}/public/assets]"
   end
 
   if new_resource.piwik_configuration
     file "#{rails_directory}/config/piwik.yml" do
       owner new_resource.user
       group new_resource.group
-      mode 0o664
+      mode "664"
       content YAML.dump(new_resource.piwik_configuration)
-      notifies :run, "execute[#{rails_directory}/public/assets]"
     end
   else
     file "#{rails_directory}/config/piwik.yml" do
       action :delete
-      notifies :run, "execute[#{rails_directory}/public/assets]"
     end
   end
 
@@ -385,6 +383,7 @@ action :create do
     group "root"
     environment "NOKOGIRI_USE_SYSTEM_LIBRARIES" => "yes"
     subscribes :run, "gem_package[bundler#{new_resource.ruby}]"
+    subscribes :run, "git[#{rails_directory}]"
     notifies :restart, "passenger_application[#{rails_directory}]"
   end
 
@@ -399,28 +398,57 @@ action :create do
     only_if { new_resource.run_migrations }
   end
 
+  package "yarnpkg" do
+    only_if { new_resource.build_assets }
+  end
+
+  execute "#{rails_directory}/package.json" do
+    action :nothing
+    command "bundle#{new_resource.ruby} exec rake yarn:install"
+    environment "HOME" => rails_directory,
+                "RAILS_ENV" => "production"
+    cwd rails_directory
+    user new_resource.user
+    group new_resource.group
+    subscribes :run, "git[#{rails_directory}]"
+    only_if { new_resource.build_assets }
+  end
+
   execute "#{rails_directory}/app/assets/javascripts/i18n" do
     action :nothing
     command "bundle#{new_resource.ruby} exec rake i18n:js:export"
-    environment "RAILS_ENV" => "production"
+    environment "HOME" => rails_directory,
+                "RAILS_ENV" => "production"
     cwd rails_directory
     user new_resource.user
     group new_resource.group
-    notifies :run, "execute[#{rails_directory}/public/assets]"
+    subscribes :run, "git[#{rails_directory}]"
+    only_if { new_resource.build_assets }
   end
 
   execute "#{rails_directory}/public/assets" do
     action :nothing
     command "bundle#{new_resource.ruby} exec rake assets:precompile"
-    environment "RAILS_ENV" => "production"
+    environment "HOME" => rails_directory,
+                "RAILS_ENV" => "production"
     cwd rails_directory
     user new_resource.user
     group new_resource.group
+    subscribes :run, "git[#{rails_directory}]"
+    subscribes :run, "file[create:#{rails_directory}/config/application.yml]"
+    subscribes :run, "file[#{rails_directory}/config/settings.local.yml]"
+    subscribes :run, "file[#{rails_directory}/config/storage.yml]"
+    subscribes :run, "file[#{rails_directory}/config/piwik.yml]"
+    subscribes :run, "execute[#{rails_directory}/package.json]"
+    subscribes :run, "execute[#{rails_directory}/app/assets/javascripts/i18n]"
     notifies :restart, "passenger_application[#{rails_directory}]"
+    only_if { new_resource.build_assets }
   end
 
   file "#{rails_directory}/public/export/embed.html" do
     action :nothing
+    subscribes :delete, "git[#{rails_directory}]"
+    subscribes :delete, "file[#{rails_directory}/config/settings.local.yml]"
   end
 
   passenger_application rails_directory do
@@ -433,7 +461,7 @@ action :create do
     source "rails.cron.erb"
     owner "root"
     group "root"
-    mode 0o755
+    mode "755"
     variables :directory => rails_directory
   end
 end
index b69b3f0e67120f279dbf23d1c3e0fc0dcf763bd8..93867a96ae8a6a1129b33bbcdbfac5ae3eb858a6 100644 (file)
   #
   # Pass supported calls to cgimap
   #
-  RewriteRule ^/api/0\.6/map$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteRule ^/api/0\.6/map(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
   RewriteCond %{REQUEST_METHOD} ^(HEAD|GET)$
-  RewriteRule ^/api/0\.6/(node|way|relation|changeset)/[0-9]+$ fcgi://127.0.0.1:8000$0 [P]
-  RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/history$ fcgi://127.0.0.1:8000$0 [P]
-  RewriteRule ^/api/0\.6/(way|relation)/[0-9]+/full$ fcgi://127.0.0.1:8000$0 [P]
-  RewriteRule ^/api/0\.6/(nodes|ways|relations)$ fcgi://127.0.0.1:8000$0 [P]
-  RewriteRule ^/api/0\.6/changeset/[0-9]+/download$ fcgi://127.0.0.1:8000$0 [P]
-  RewriteRule ^/api/0\.6/changeset/[0-9]+/upload$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteRule ^/api/0\.6/(node|way|relation|changeset)/[0-9]+(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/history(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/relations(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteRule ^/api/0\.6/node/[0-9]+/ways(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteRule ^/api/0\.6/(way|relation)/[0-9]+/full(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteRule ^/api/0\.6/(nodes|ways|relations)(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteRule ^/api/0\.6/changeset/[0-9]+/(upload|download)(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
 </VirtualHost>
 
 <Directory <%= node[:web][:base_directory] %>/rails/public>
index 4c283299b2f8cedc2b866834fa227b0aac595ffe..19854189b6b3d52d2b812bf743261b51c0611662 100644 (file)
@@ -12,7 +12,6 @@
   # Enable SSL
   #
   SSLEngine on
-  SSLProxyEngine on
   SSLCertificateFile /etc/ssl/certs/www.openstreetmap.org.pem
   SSLCertificateKeyFile /etc/ssl/private/www.openstreetmap.org.key
 
   RewriteCond %{HTTP_USER_AGENT} "OSMApp Tuner"
   RewriteRule . - [F,L]
 
-  #
-  # Block requests for the old 404 map tile
-  # and force cache headers on response
-  #
-  <Location /openlayers/img/404.png>
-    Header always set Cache-Control "public, max-age=31536000, immutable"
-    Header always set Expires "Tue, 19 Jan 2038 03:14:07 GMT"
-    RewriteRule ^ - [G,L]
-  </Location>
-
   #
   # Block attempts to access old API versions
   #
   #
   RewriteRule ^/api/0.6/changeset/6823497/download$ - [F,L]
 
+  #
+  # Ignore Vicon Valerus "online" status pings
+  # https://gist.github.com/Firefishy/86ed5b86991b225179b54bbafbcd769e
+  #
+  RewriteCond "%{QUERY_STRING}" "^q=abcde&t=20"
+  RewriteRule "^/api/0\.6/notes/search$" - [R=204,L]
+
   #
   # Force special MIME type for crossdomain.xml files
   #
     ExpiresDefault "access plus 10 years"
   </Location>
   <Location /openlayers/>
-    ExpiresDefault "access plus 7 days"
+    Header unset Last-Modified
+    FileETag Size
+
+    Header always set Cache-Control "public, max-age=31536000, immutable"
+    Header always set Expires "Tue, 19 Jan 2038 03:14:07 GMT"
   </Location>
 
   #
   SetEnv OPENSTREETMAP_STATUS <%= @status %>
   SetEnv SECRET_KEY_BASE <%= @secret_key_base %>
   Alias /favicon.ico <%= node[:web][:base_directory] %>/rails/app/assets/favicons/favicon.ico
-  Alias /openlayers <%= node[:web][:base_directory] %>/rails/vendor/assets/openlayers
+  Alias /openlayers <%= node[:web][:base_directory] %>/static/openlayers
   Alias /stats /store/rails/stats
   Alias /user/image /store/rails/user/image
   Alias /attachments /store/rails/attachments
 
   #
-  # Preserve the host name when forwarding to the proxy
+  # Pass authentication related headers to cgimap
   #
-  ProxyPreserveHost on
-
-  #
-  # Set a long timeout - changeset uploads can take a long time
-  #
-  ProxyTimeout 3600
-
-  #
-  # Allow all proxy requests
-  #
-  <Proxy *>
-    Require all granted
-  </Proxy>
+  <Location />
+    CGIPassAuth On
+  </Location>
 
   #
-  # Pass some other API calls to the backends via a load balancer
+  # Pass supported calls to cgimap
   #
-  ProxyPass /api/0.6/map balancer://backend/api/0.6/map
-  ProxyPass /api/0.6/tracepoints balancer://backend/api/0.6/tracepoints
-  ProxyPass /api/0.6/amf/read balancer://backend/api/0.6/amf/read
-  ProxyPass /api/0.6/swf/trackpoints balancer://backend/api/0.6/swf/trackpoints
-  ProxyPassMatch ^(/api/0\.6/changeset/[0-9]+)$ balancer://backend$1
-  ProxyPassMatch ^(/api/0\.6/changeset/[0-9]+/upload)$ balancer://amsterdam$1
-  ProxyPassMatch ^(/api/0\.6/changeset/[0-9]+/download)$ balancer://backend$1
-  ProxyPassMatch ^(/api/0\.6/(node|way|relation)/[0-9]+)$ balancer://backend$1
-  ProxyPassMatch ^(/api/0\.6/(node|way|relation)/[0-9]+/(full|history|search|ways))$ balancer://backend$1
-  ProxyPass /api/0.6/nodes balancer://backend/api/0.6/nodes
-  ProxyPass /api/0.6/ways balancer://backend/api/0.6/ways
-  ProxyPass /api/0.6/relations balancer://backend/api/0.6/relations
-  ProxyPassMatch ^(/trace/[0-9]+/data(|/|.xml))$ balancer://backend$1
+  RewriteRule ^/api/0\.6/map(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteCond %{REQUEST_METHOD} ^(HEAD|GET)$
+  RewriteRule ^/api/0\.6/(node|way|relation|changeset)/[0-9]+(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/history(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteRule ^/api/0\.6/(node|way|relation)/[0-9]+/relations(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteRule ^/api/0\.6/node/[0-9]+/ways(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteRule ^/api/0\.6/(way|relation)/[0-9]+/full(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteRule ^/api/0\.6/(nodes|ways|relations)(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
+  RewriteRule ^/api/0\.6/changeset/[0-9]+/(upload|download)(\.json|\.xml)?$ fcgi://127.0.0.1:8000$0 [P]
 
   #
   # Redirect trac and wiki requests to the right places
   RedirectPermanent /images/cc_button.png https://www.openstreetmap.org/assets/cc_button.png
 
   #
-  # Define a load balancer for the local backends
-  #
-  <Proxy balancer://backend>
-    ProxySet lbmethod=bybusyness
-<% node[:web][:backends].each do |backend| -%>
-    BalancerMember https://<%= backend %> disablereuse=on
-<% end -%>
-  </Proxy>
-
-  #
-  # Define a load balancer for the Amsterdam backends
-  #
-  <Proxy balancer://amsterdam>
-    ProxySet lbmethod=bybusyness
-<% ["rails1.ams", "rails2.ams", "rails3.ams"].each do |backend| -%>
-    BalancerMember https://<%= backend %> disablereuse=on
-<% end -%>
-  </Proxy>
-
-  #
-  # Define a load balancer for the Bytemark backends
-  #
-  <Proxy balancer://bytemark>
-    ProxySet lbmethod=bybusyness
-<% ["rails4.bm", "rails5.bm"].each do |backend| -%>
-    BalancerMember https://<%= backend %> disablereuse=on
-<% end -%>
-  </Proxy>
-
-  #
-  # Redirect api requests made to www.osm.org to api.osm.org
+  # Redirect api requests made to www.openstreetmap.org to api.openstreetmap.org
   #
 #  RewriteCond %{HTTP_HOST} =www.openstreetmap.org
 #  RewriteRule ^/api/(.*)$ https://api.openstreetmap.org/api/$1 [L,NE,R=permanent]
 
   #
-  # Redirect non-api requests made to api.osm.org to www.osm.org
+  # Redirect non-api requests made to api.openstreetmap.org to www.openstreetmap.org
   #
   RewriteCond %{HTTP_HOST} =api.openstreetmap.org
   RewriteCond %{REQUEST_URI} !^/api/
   RedirectPermanent / https://www.openstreetmap.org/
 </VirtualHost>
 
+<VirtualHost *:80>
+  ServerName osm.org
+
+  Header always set Cache-Control "max-age=31536000"
+  Header always set Expires "Tue, 19 Jan 2038 03:14:07 GMT"
+
+  RewriteEngine on
+
+  RewriteRule ^/\.well-known/acme-challenge/(.*)$ http://acme.openstreetmap.org/.well-known/acme-challenge/$1 [R=permanent,L]
+
+  RewriteCond %{REQUEST_URI} !^/server-status$
+  RewriteRule ^(.*)$ https://osm.org$1 [L,NE,R=permanent]
+</VirtualHost>
+
+<VirtualHost *:80>
+  ServerName www.osm.org
+
+  Header always set Cache-Control "max-age=31536000"
+  Header always set Expires "Tue, 19 Jan 2038 03:14:07 GMT"
+
+  RewriteEngine on
+
+  RewriteRule ^/\.well-known/acme-challenge/(.*)$ http://acme.openstreetmap.org/.well-known/acme-challenge/$1 [R=permanent,L]
+
+  RewriteCond %{REQUEST_URI} !^/server-status$
+  RewriteRule ^(.*)$ https://www.osm.org$1 [L,NE,R=permanent]
+</VirtualHost>
+
 <VirtualHost *:80>
   ServerName openstreetmap.org
 
   </FilesMatch>
 </Directory>
 
+<Directory /srv/www.openstreetmap.org/static>
+  Require all granted
+</Directory>
+
 <Directory /srv/www.openstreetmap.org/rails/app/assets>
   Require all granted
 </Directory>
index b4c4174476f48824cac2f3d6ca827a0d255ef364..f894af5c42a70f90ab9897f669b6e26af227f109 100644 (file)
@@ -21,22 +21,80 @@ end
 
 parser = ApacheLogRegex.new('%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %Dus %{UNIQUE_ID}e %{SSL_PROTOCOL}x %{SSL_CIPHER}x')
 last_write = Time.now
-statistics = { :status => Hash.new(0), :uri => Hash.new(0) }
+
+statistics = {
+  :status => Hash.new(0),
+  :uri => Hash.new(0),
+  :count => Hash.new(0),
+  :bytes => Hash.new(0),
+  :seconds => Hash.new(0.0),
+  :ssl => Hash.new(0)
+}
 
 File::Tail::Logfile.tail("/var/log/apache2/access.log") do |line|
   begin
     hash = parser.parse(line)
-    status = hash["%>s"]
+
     uri = categorise_uri(hash["%r"])
+    status = hash["%>s"]
+    bytes = hash["%O"].to_i
+    seconds = hash["%Dus"].to_f / 1000000
+    protocol = hash["%{SSL_PROTOCOL}x"]
+    cipher = hash["%{SSL_CIPHER}x"]
 
     statistics[:status][status] += 1
     statistics[:uri][uri] += 1
+    statistics[:count][[uri, status]] += 1
+    statistics[:bytes][[uri, status]] += bytes
+    statistics[:seconds][[uri, status]] += seconds
+    statistics[:ssl][[protocol, cipher]] += 1 unless protocol == "-"
   rescue ApacheLogRegex::ParseError
     # nil
   end
 
   if Time.now - last_write > 10
-    File.write("/srv/www.openstreetmap.org/rails/tmp/statistics.json", statistics.to_json)
+    File.write("/srv/www.openstreetmap.org/rails/tmp/statistics.json", statistics.slice(:status, :uri).to_json)
+
+    File.open("/var/lib/prometheus/node-exporter/api.tmp", "w") do |file|
+      file.puts "# HELP api_call_count_total Number of calls by type and status"
+      file.puts "# TYPE api_call_count_total counter"
+
+      statistics[:count].each do |key, value|
+        uri, status = key
+
+        file.puts "api_call_count_total{uri=\"#{uri}\",status=\"#{status}\"} #{value}"
+      end
+
+      file.puts "# HELP api_call_bytes_total Number of bytes returned by type and status"
+      file.puts "# TYPE api_call_bytes_total counter"
+
+      statistics[:bytes].each do |key, value|
+        uri, status = key
+
+        file.puts "api_call_bytes_total{uri=\"#{uri}\",status=\"#{status}\"} #{value}"
+      end
+
+      file.puts "# HELP api_call_seconds_total Number of seconds returned by type and status"
+      file.puts "# TYPE api_call_seconds_total counter"
+
+      statistics[:seconds].each do |key, value|
+        uri, status = key
+
+        file.puts "api_call_seconds_total{uri=\"#{uri}\",status=\"#{status}\"} #{value}"
+      end
+
+      file.puts "# HELP api_call_ssl_total Number of calls by SSL protocol and cipher"
+      file.puts "# TYPE api_call_ssl_total counter"
+
+      statistics[:ssl].each do |key, value|
+        protocol, cipher = key
+
+        file.puts "api_call_ssl_total{protocol=\"#{protocol}\",cipher=\"#{cipher}\"} #{value}"
+      end
+    end
+
+    File.rename("/var/lib/prometheus/node-exporter/api.tmp", "/var/lib/prometheus/node-exporter/api.prom")
+
     last_write = Time.now
   end
 end
index 7e78682d205f8af4a1e0943840bec8418ccc8fc4..0b77f3aa725ca3615c9b9805eae91beeb8d285cf 100644 (file)
@@ -7,4 +7,3 @@ description       "Installs and configures servers for wiki.openstreetmap.org"
 version           "1.0.0"
 supports          "ubuntu"
 depends           "mediawiki"
-depends           "squid"
index 47625ae0d5935241c4baa9d7c60409bd57029f83..72af19cb80ef3fe16f17a10e70660f8515ba2d5e 100644 (file)
@@ -17,8 +17,6 @@
 # limitations under the License.
 #
 
-# include_recipe "squid"
-
 include_recipe "mediawiki"
 
 passwords = data_bag_item("wiki", "passwords")
@@ -35,6 +33,12 @@ mediawiki_site "wiki.openstreetmap.org" do
            "wiki.openstreetmap.pro", "wiki.openstreetmaps.org"]
   directory "/srv/wiki.openstreetmap.org"
 
+  fpm_max_children 50
+  fpm_start_servers 10
+  fpm_min_spare_servers 10
+  fpm_max_spare_servers 20
+  fpm_prometheus_port 9253
+
   database_name "wiki"
   database_user "wiki-user"
   database_password passwords["database"]
@@ -78,7 +82,7 @@ end
 
 mediawiki_extension "OsmWikibase" do
   site "wiki.openstreetmap.org"
-  repository "git://github.com/nyurik/OsmWikibase.git"
+  repository "https://github.com/nyurik/OsmWikibase.git"
   reference "master"
 end
 
@@ -108,20 +112,20 @@ end
 cookbook_file "/srv/wiki.openstreetmap.org/osm_logo_wiki.png" do
   owner node[:mediawiki][:user]
   group node[:mediawiki][:group]
-  mode 0o644
+  mode "644"
 end
 
 template "/srv/wiki.openstreetmap.org/robots.txt" do
   owner node[:mediawiki][:user]
   group node[:mediawiki][:group]
-  mode 0o644
+  mode "644"
   source "robots.txt.erb"
 end
 
 cookbook_file "/srv/wiki.openstreetmap.org/favicon.ico" do
   owner node[:mediawiki][:user]
   group node[:mediawiki][:group]
-  mode 0o644
+  mode "644"
 end
 
 directory "/srv/wiki.openstreetmap.org/dump" do
@@ -130,10 +134,9 @@ directory "/srv/wiki.openstreetmap.org/dump" do
   mode "0775"
 end
 
-template "/etc/cron.d/wiki-dump" do
-  owner "root"
-  group "root"
-  mode 0o644
-  source "wiki-dump.erb"
-  variables :directory => "/srv/wiki.openstreetmap.org"
+cron_d "wiki-dump" do
+  minute "0"
+  hour "2"
+  user "wiki"
+  command "cd /srv/wiki.openstreetmap.org && php w/maintenance/dumpBackup.php --full --quiet --output=gzip:dump/dump.xml.gz"
 end
index 7d214127b77832a62ba01fae21a9a8002805fe98..ddcfb62a78ce6397226b6f525d004913ce1dfbc3 100644 (file)
@@ -9,9 +9,29 @@ require_once "$IP/extensions/MultiMaps/MultiMaps.php";
 # denote different tiles within a BaseMapService
 $egMultiMaps_MapServices = [
   'Leaflet',
+  'cyclosm' => [
+    'service' => 'Leaflet',
+    'attribution' => '&copy; <a href="https://osm.org/copyright">OpenStreetMap contributors</a>. Tiles style by <a href="https://www.cyclosm.org/" target="_blank">CyclOSM</a> hosted by <a href="https://openstreetmap.fr/" target="_blank">OpenStreetMap France</a>',
+    'source' => 'https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png',
+  ],
+  'cycle' => [
+    'service' => 'Leaflet',
+    'attribution' => '&copy; <a href="https://osm.org/copyright">OpenStreetMap contributors</a>. Tiles courtesy of <a href="https://www.thunderforest.com/" target="_blank">Andy Allan</a>',
+    'source' => 'https://tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey=<%= @thunderforest_key %>',
+  ],
   'transport' => [
     'service' => 'Leaflet',
     'attribution' => '&copy; <a href="https://osm.org/copyright">OpenStreetMap contributors</a>. Tiles courtesy of <a href="https://www.thunderforest.com/" target="_blank">Andy Allan</a>',
     'source' => 'https://tile.thunderforest.com/transport/{z}/{x}/{y}.png?apikey=<%= @thunderforest_key %>',
   ],
+  'oepnv' => [
+    'service' => 'Leaflet',
+    'attribution' => '&copy; <a href="https://osm.org/copyright">OpenStreetMap contributors</a>. Tiles courtesy of <a href="https://memomaps.de/" target="_blank">MeMoMaps</a>',
+    'source' => 'https://tileserver.memomaps.de/tilegen/{z}/{x}/{y}.png',
+  ],
+  'humanitarian' => [
+    'service' => 'Leaflet',
+    'attribution' => '&copy; <a href="https://osm.org/copyright">OpenStreetMap contributors</a>. Tiles style by <a href="https://www.hotosm.org/" target="_blank">Humanitarian OpenStreetMap team</a> hosted by <a href="https://openstreetmap.fr/" target="_blank">OpenStreetMap France</a>',
+    'source' => 'https://tile.openstreetmap.fr/hot/{z}/{x}/{y}.png'
+  ],
 ];
index 6bbede43fbf55e1d49d91d027f4e9dae0488ab82..da194cad74efeecfbaa749ca045bb6a3fb130168 100644 (file)
@@ -38,7 +38,7 @@ call_user_func( function() {
     $wgWBRepoSettings['entityNamespaces']['property'] = WB_NS_PROPERTY;
 
     // Make sure we use the same keys on repo and clients, so we can share cached objects.
-    $wgWBRepoSettings['sharedCacheKeyPrefix'] = $wgDBname . ':WBL/' . rawurlencode( WBL_VERSION );
+    $wgWBRepoSettings['sharedCacheKeyPrefix'] = $wgDBname;
 
     // Include Wikibase items in the regular search result by default
     $wgNamespacesToBeSearchedDefault[WB_NS_ITEM] = true;
@@ -91,8 +91,3 @@ $wgGroupPermissions['data-admin']['property-create'] = true;
 
 // See https://www.mediawiki.org/wiki/Wikibase/Installation/Advanced_configuration#Define_links_for_external_identifiers
 $wgWBRepoSettings['formatterUrlProperty'] = 'P8';
-
-// Disable Wikibase searchbox with this hack (hopefully Wikibase will implement support for it soon)
-// See https://phabricator.wikimedia.org/T205560
-// After upgrading to Wikibase 1.33, this line can be deleted. The 'enableEntitySearchUI' above will do the same thing.
-$wgResourceModules['wikibase.ui.entitysearch']['scripts'] = [];
diff --git a/cookbooks/wiki/templates/default/wiki-dump.erb b/cookbooks/wiki/templates/default/wiki-dump.erb
deleted file mode 100644 (file)
index 8139f28..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# DO NOT EDIT - This file is being maintained by Chef
-
-0 2 * * * wiki cd <%= @directory %> && php w/maintenance/dumpBackup.php --full --quiet --output=gzip:dump/dump.xml.gz
index 9cd3956483de21ddd037becfcfa0594ec25a0014..9233459dcf346fb45148cb1829a9c09c5316ac28 100644 (file)
@@ -1,9 +1,6 @@
 # Enable the "wordpress" role
 default[:accounts][:users][:wordpress][:status] = :role
 
-# Use prefork as PHP is to dumb for anything else
-default[:apache][:mpm] = "prefork"
-
 # Set wordpress defaults
 default[:wordpress][:user] = "wordpress"
 default[:wordpress][:group] = "wordpress"
index 1c2fbcb6a4325618c1a1edee5bee1311d627b2d1..dead032567067bb44028ce4b077a461d6ea59664 100644 (file)
@@ -1,5 +1,6 @@
 require "chef/mixin/shell_out"
 
+require "addressable"
 require "httpclient"
 require "php_serialize"
 
index 6aaf827455585efb37c756a8538a91b1f45f5314..ae7816541299744c616be3840a48b2fff69fe8dd 100644 (file)
@@ -6,9 +6,13 @@ description       "Installs and configures Wordpress"
 
 version           "1.0.0"
 supports          "ubuntu"
+depends           "accounts"
 depends           "apache"
 depends           "chef"
+depends           "fail2ban"
+depends           "git"
 depends           "mysql"
+depends           "php"
 depends           "ssl"
 gem               "httpclient"
 gem               "php_serialize"
index 52c544db53f1d8d3389c695e2a3f1eadc59f385b..73f6f353e4303f32974dcdba471bfa66e99c04fa 100644 (file)
 # limitations under the License.
 #
 
+include_recipe "accounts"
 include_recipe "apache"
+include_recipe "fail2ban"
+include_recipe "git"
 include_recipe "mysql"
+include_recipe "php::fpm"
 
 package %w[
   subversion
-  php
   php-mysql
 ]
 
-apache_module "php7.2"
+apache_module "proxy"
+apache_module "proxy_fcgi"
 apache_module "rewrite"
 
 fail2ban_filter "wordpress" do
index 778ff6583d98bd5f261dec480a42c29c6e60a471..ccc8010d5d2dfaae52ce22d8ef064df0d55d6dac 100644 (file)
@@ -19,7 +19,7 @@
 
 default_action :create
 
-property :plugin, :kind_of => String, :name_attribute => true
+property :plugin, :kind_of => String, :name_property => true
 property :site, :kind_of => String, :required => true
 property :source, :kind_of => String
 property :version, :kind_of => String
@@ -34,10 +34,10 @@ action :create do
       source new_resource.source
       owner node[:wordpress][:user]
       group node[:wordpress][:group]
-      mode 0o755
+      mode "755"
       files_owner node[:wordpress][:user]
       files_group node[:wordpress][:group]
-      files_mode 0o755
+      files_mode "755"
     end
   else
     plugin_repository = new_resource.repository || default_repository
@@ -47,6 +47,7 @@ action :create do
         action :sync
         repository plugin_repository
         revision new_resource.revision
+        depth 1
         user node[:wordpress][:user]
         group node[:wordpress][:group]
       end
index 72af236b6baa2bb96c7e3abf79628bdafe2769c4..5570fb7b2e997243d711f6f0fb2c052c9d9ad5a8 100644 (file)
@@ -20,32 +20,38 @@ require "securerandom"
 
 default_action :create
 
-property :site, :kind_of => String, :name_attribute => true
+property :site, :kind_of => String, :name_property => true
 property :aliases, :kind_of => [String, Array]
 property :directory, :kind_of => String
 property :version, :kind_of => String
 property :database_name, :kind_of => String, :required => true
-property :database_user, :kind_of => String, :required => true
-property :database_password, :kind_of => String, :required => true
+property :database_user, :kind_of => String, :required => [:create]
+property :database_password, :kind_of => String, :required => [:create]
 property :database_prefix, :kind_of => String, :default => "wp_"
 property :urls, :kind_of => Hash, :default => {}
+property :fpm_max_children, :kind_of => Integer, :default => 5
+property :fpm_start_servers, :kind_of => Integer, :default => 2
+property :fpm_min_spare_servers, :kind_of => Integer, :default => 1
+property :fpm_max_spare_servers, :kind_of => Integer, :default => 3
+property :fpm_request_terminate_timeout, :kind_of => Integer, :default => 300
+property :fpm_prometheus_port, :kind_of => Integer
 property :reload_apache, :kind_of => [TrueClass, FalseClass], :default => true
 
 action :create do
   version = new_resource.version || Chef::Wordpress.current_version
 
-  node.normal_unless[:wordpress][:sites][new_resource.site] = {}
+  node.default[:wordpress][:sites][new_resource.site] = {
+    :directory => site_directory
+  }
 
-  node.normal[:wordpress][:sites][new_resource.site][:directory] = site_directory
-
-  node.normal_unless[:wordpress][:sites][new_resource.site][:auth_key] = SecureRandom.base64(48)
-  node.normal_unless[:wordpress][:sites][new_resource.site][:secure_auth_key] = SecureRandom.base64(48)
-  node.normal_unless[:wordpress][:sites][new_resource.site][:logged_in_key] = SecureRandom.base64(48)
-  node.normal_unless[:wordpress][:sites][new_resource.site][:nonce_key] = SecureRandom.base64(48)
-  node.normal_unless[:wordpress][:sites][new_resource.site][:auth_salt] = SecureRandom.base64(48)
-  node.normal_unless[:wordpress][:sites][new_resource.site][:secure_auth_salt] = SecureRandom.base64(48)
-  node.normal_unless[:wordpress][:sites][new_resource.site][:logged_in_salt] = SecureRandom.base64(48)
-  node.normal_unless[:wordpress][:sites][new_resource.site][:nonce_salt] = SecureRandom.base64(48)
+  auth_key = persistent_token("wordpress", new_resource.site, "auth_key")
+  secure_auth_key = persistent_token("wordpress", new_resource.site, "secure_auth_key")
+  logged_in_key = persistent_token("wordpress", new_resource.site, "logged_in_key")
+  nonce_key = persistent_token("wordpress", new_resource.site, "nonce_key")
+  auth_salt = persistent_token("wordpress", new_resource.site, "auth_salt")
+  secure_auth_salt = persistent_token("wordpress", new_resource.site, "secure_auth_salt")
+  logged_in_salt = persistent_token("wordpress", new_resource.site, "logged_in_salt")
+  nonce_salt = persistent_token("wordpress", new_resource.site, "nonce_salt")
 
   mysql_user "#{new_resource.database_user}@localhost" do
     password new_resource.database_password
@@ -58,7 +64,7 @@ action :create do
   declare_resource :directory, site_directory do
     owner node[:wordpress][:user]
     group node[:wordpress][:group]
-    mode 0o755
+    mode "755"
   end
 
   subversion site_directory do
@@ -75,14 +81,14 @@ action :create do
     line.gsub!(/password_here/, new_resource.database_password)
     line.gsub!(/wp_/, new_resource.database_prefix)
 
-    line.gsub!(/('AUTH_KEY', *)'put your unique phrase here'/, "\\1'#{node[:wordpress][:sites][new_resource.site][:auth_key]}'")
-    line.gsub!(/('SECURE_AUTH_KEY', *)'put your unique phrase here'/, "\\1'#{node[:wordpress][:sites][new_resource.site][:secure_auth_key]}'")
-    line.gsub!(/('LOGGED_IN_KEY', *)'put your unique phrase here'/, "\\1'#{node[:wordpress][:sites][new_resource.site][:logged_in_key]}'")
-    line.gsub!(/('NONCE_KEY', *)'put your unique phrase here'/, "\\1'#{node[:wordpress][:sites][new_resource.site][:nonce_key]}'")
-    line.gsub!(/('AUTH_SALT', *)'put your unique phrase here'/, "\\1'#{node[:wordpress][:sites][new_resource.site][:auth_salt]}'")
-    line.gsub!(/('SECURE_AUTH_SALT', *)'put your unique phrase here'/, "\\1'#{node[:wordpress][:sites][new_resource.site][:secure_auth_salt]}'")
-    line.gsub!(/('LOGGED_IN_SALT', *)'put your unique phrase here'/, "\\1'#{node[:wordpress][:sites][new_resource.site][:logged_in_salt]}'")
-    line.gsub!(/('NONCE_SALT', *)'put your unique phrase here'/, "\\1'#{node[:wordpress][:sites][new_resource.site][:nonce_salt]}'")
+    line.gsub!(/('AUTH_KEY', *)'put your unique phrase here'/, "\\1'#{auth_key}'")
+    line.gsub!(/('SECURE_AUTH_KEY', *)'put your unique phrase here'/, "\\1'#{secure_auth_key}'")
+    line.gsub!(/('LOGGED_IN_KEY', *)'put your unique phrase here'/, "\\1'#{logged_in_key}'")
+    line.gsub!(/('NONCE_KEY', *)'put your unique phrase here'/, "\\1'#{nonce_key}'")
+    line.gsub!(/('AUTH_SALT', *)'put your unique phrase here'/, "\\1'#{auth_salt}'")
+    line.gsub!(/('SECURE_AUTH_SALT', *)'put your unique phrase here'/, "\\1'#{secure_auth_salt}'")
+    line.gsub!(/('LOGGED_IN_SALT', *)'put your unique phrase here'/, "\\1'#{logged_in_salt}'")
+    line.gsub!(/('NONCE_SALT', *)'put your unique phrase here'/, "\\1'#{nonce_salt}'")
 
     if line =~ /define\('WP_DEBUG'/
       line += "\n"
@@ -100,14 +106,14 @@ action :create do
   file "#{site_directory}/wp-config.php" do
     owner node[:wordpress][:user]
     group node[:wordpress][:group]
-    mode 0o644
+    mode "644"
     content wp_config
   end
 
   declare_resource :directory, "#{site_directory}/wp-content/uploads" do
     owner "www-data"
     group "www-data"
-    mode 0o755
+    mode "755"
   end
 
   file "#{site_directory}/sitemap.xml" do
@@ -122,7 +128,7 @@ action :create do
     cookbook "wordpress"
     owner node[:wordpress][:user]
     group node[:wordpress][:group]
-    mode 0o644
+    mode "644"
     backup false
   end
 
@@ -130,6 +136,19 @@ action :create do
     domains [new_resource.site] + Array(new_resource.aliases)
   end
 
+  php_fpm new_resource.site do
+    pm_max_children new_resource.fpm_max_children
+    pm_start_servers new_resource.fpm_start_servers
+    pm_min_spare_servers new_resource.fpm_min_spare_servers
+    pm_max_spare_servers new_resource.fpm_max_spare_servers
+    request_terminate_timeout new_resource.fpm_request_terminate_timeout
+    php_admin_values "open_basedir" => "#{site_directory}/:/usr/share/php/:/tmp/",
+                     "disable_functions" => "exec,shell_exec,system,passthru,popen,proc_open"
+    php_values "upload_max_filesize" => "70M",
+               "post_max_size" => "100M"
+    prometheus_port new_resource.fpm_prometheus_port
+  end
+
   apache_site new_resource.site do
     cookbook "wordpress"
     template "apache.erb"
@@ -195,6 +214,7 @@ end
 
 action_class do
   include Chef::Mixin::EditFile
+  include Chef::Mixin::PersistentToken
 
   def site_directory
     new_resource.directory || "/srv/#{new_resource.site}"
index d98edb25dd43694a050345ad583dce1fbe9e8ccd..3e8fabe94af4e8faa52f5e79076d5edb4543f02c 100644 (file)
@@ -19,7 +19,7 @@
 
 default_action :create
 
-property :theme, :kind_of => String, :name_attribute => true
+property :theme, :kind_of => String, :name_property => true
 property :site, :kind_of => String, :required => true
 property :source, :kind_of => String
 property :version, :kind_of => String
@@ -34,10 +34,10 @@ action :create do
       source new_resource.source
       owner node[:wordpress][:user]
       group node[:wordpress][:group]
-      mode 0o755
+      mode "755"
       files_owner node[:wordpress][:user]
       files_group node[:wordpress][:group]
-      files_mode 0o644
+      files_mode "644"
     end
   else
     theme_repository = new_resource.repository || default_repository
@@ -47,6 +47,7 @@ action :create do
         action :sync
         repository theme_repository
         revision new_resource.revision
+        depth 1
         user node[:wordpress][:user]
         group node[:wordpress][:group]
       end
index 34c25059d659cd84db200dd2e853377a7459ba8a..a1187818a55d60d3527b6f614af36c9588181f96 100644 (file)
   Alias <%= url %> <%= directory %>
   <Directory <%= directory %>>
     AllowOverride None
-    php_admin_flag engine off
     Require all granted
+    <FilesMatch ".+\.ph(ar|p|tml)$">
+      SetHandler None
+    </FilesMatch>
   </Directory>
 <% end -%>
 
-  php_admin_value open_basedir <%= @directory %>/:/usr/share/php/:/tmp/
-  php_admin_value disable_functions "exec,shell_exec,system,passthru,popen,proc_open"
-  php_value upload_max_filesize 70M
-  php_value post_max_size 100M
-
   <Directory <%= @directory %>>
     RewriteEngine on
 
     AllowOverride AuthConfig
 
     Require all granted
+
+    <FilesMatch ".+\.ph(ar|p|tml)$">
+      SetHandler "proxy:unix:/run/php/<%= @name %>.sock|fcgi://127.0.0.1"
+    </FilesMatch>
   </Directory>
 
   <Files <%= @directory %>/wp-config.php>
@@ -71,7 +72,9 @@
   <Directory <%= @directory %>/uploads>
     AllowOverride None
     AddType text/plain .html .htm .shtml
-    php_admin_flag engine off
+    <FilesMatch ".+\.ph(ar|p|tml)$">
+      SetHandler None
+    </FilesMatch>
   </Directory>
 
   <Directory ~ "\.svn">
index cb7bc82d55348a9c92229c160e2cdf512b5c1282..60d6659326ff7908b9cf25fa8f9d1553c42523e5 100755 (executable)
@@ -12,7 +12,7 @@ if IO.popen(["git", "ls-files", "--unmerged"]).read.empty?
   end.compact
 
   ruby_files = files.select do |file|
-    file =~ /\.rb$/ || (file !~ /\.erb$/ && `file --brief --mime-type #{file}` == "text/x-ruby\n")
+    file =~ /\.rb$/ || (file !~ /\.erb$/ && %x(file --brief --mime-type #{file}) == "text/x-ruby\n")
   end
 
   ok &&= system("bundle", "exec", "rubocop", *ruby_files) unless ruby_files.empty?
index 7e2b97e8bfe30d6223305e5d192831d7091ee9dc..8cab0ea355ed9202539fe48635a22a77c164e0c6 100644 (file)
@@ -10,15 +10,15 @@ default_attributes(
   },
   :hosted_by => "AARNet",
   :location => "Carlton, Victoria, Australia",
-  :timezone => "Australia/Melbourne",
-  :networking => {
-    :nameservers => ["202.158.207.1", "202.158.207.2"]
-  }
+  :timezone => "Australia/Melbourne"
 )
 
 override_attributes(
+  :networking => {
+    :nameservers => ["202.158.207.1", "202.158.207.2"]
+  },
   :ntp => {
-    :servers => ["0.au.pool.ntp.org", "1.au.pool.ntp.org", "europe.pool.ntp.org"]
+    :servers => ["0.au.pool.ntp.org", "1.au.pool.ntp.org", "oceania.pool.ntp.org"]
   }
 )
 
diff --git a/roles/albi.rb b/roles/albi.rb
new file mode 100644 (file)
index 0000000..21a4bcb
--- /dev/null
@@ -0,0 +1,61 @@
+name "albi"
+description "Master role applied to albi"
+
+default_attributes(
+  :networking => {
+    :interfaces => {
+      :external_ipv4 => {
+        :interface => "enp1s0f0",
+        :role => :external,
+        :family => :inet,
+        :address => "51.159.53.238",
+        :prefix => "24",
+        :gateway => "51.159.53.1"
+      },
+      :external_ipv6 => {
+        :interface => "enp1s0f0",
+        :role => :external,
+        :family => :inet6,
+        :address => "2001:bc8:1200:4:dac4:97ff:fe8a:9cfc",
+        :prefix => "64",
+        :gateway => "fe80::a293:51ff:fea2:ded5"
+      }
+    }
+  },
+  :postgresql => {
+    :settings => {
+      :defaults => {
+        :shared_buffers => "8GB",
+        :maintenance_work_mem => "7144MB",
+        :effective_cache_size => "16GB"
+      }
+    }
+  },
+  :sysctl => {
+    :postgres => {
+      :comment => "Increase shared memory for postgres",
+      :parameters => {
+        "kernel.shmmax" => 9 * 1024 * 1024 * 1024,
+        "kernel.shmall" => 9 * 1024 * 1024 * 1024 / 4096
+      }
+    }
+  },
+  :tile => {
+    :database => {
+      :cluster => "12/main",
+      :postgis => "3"
+    },
+    :styles => {
+      :default => {
+        :tile_directories => [
+          { :name => "/store/tiles/default", :min_zoom => 0, :max_zoom => 19 }
+        ]
+      }
+    }
+  }
+)
+
+run_list(
+  "role[scaleway]",
+  "role[tile]"
+)
index 78f67129589a3730fb831e280976c07a755e940e..ae9d720fc5a2aa9b722a67aa852e70a9cc0434d1 100644 (file)
@@ -3,23 +3,15 @@ description "Role applied to all servers at AltaVoz"
 
 default_attributes(
   :hosted_by => "AltaVoz",
-  :location => "Viña del Mar, Chile",
-  :networking => {
-    :nameservers => [
-      "200.91.44.10",
-      "200.91.41.10"
-    ],
-    :roles => {
-      :external => {
-        :zone => "av"
-      }
-    }
-  }
+  :location => "Viña del Mar, Chile"
 )
 
 override_attributes(
+  :networking => {
+    :nameservers => ["200.91.44.10", "200.91.41.10"]
+  },
   :ntp => {
-    :servers => ["0.cl.pool.ntp.org", "1.cl.pool.ntp.org", "america.pool.ntp.org"]
+    :servers => ["0.cl.pool.ntp.org", "1.cl.pool.ntp.org", "south-america.pool.ntp.org"]
   }
 )
 
index 65dfc1ed1f6e4151a2e987bb449e35c70d7e9963..12ebea0d5d3ee3fc532aec72df2536df8c8f1618 100644 (file)
@@ -2,6 +2,9 @@ name "angor"
 description "Master role applied to angor"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "18g"
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -23,17 +26,17 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "6100 MB",
-    :cache_dir => "coss /store/squid/coss-01 80000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "16384 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
   },
   :tilecache => {
-    :tile_parent => "capetown.render.openstreetmap.org",
-    :tile_siblings => [
-      "katie.openstreetmap.org",
-      "konqi.openstreetmap.org",
-      "ridgeback.openstreetmap.org",
-      "gorynych.openstreetmap.org"
-    ]
+    :tile_parent => "capetown.render.openstreetmap.org"
   }
 )
 
diff --git a/roles/appliwave.rb b/roles/appliwave.rb
new file mode 100644 (file)
index 0000000..25b4c3e
--- /dev/null
@@ -0,0 +1,25 @@
+name "appliwave"
+description "Role applied to all servers at Appliwave"
+
+default_attributes(
+  :accounts => {
+    :users => {
+      :appliwave => { :status => :administrator }
+    }
+  },
+  :hosted_by => "Appliwave",
+  :location => "Croissy-Beaubourg, France"
+)
+
+override_attributes(
+  :networking => {
+    :nameservers => ["185.73.206.93", "185.73.206.94"]
+  },
+  :ntp => {
+    :servers => ["0.fr.pool.ntp.org", "1.fr.pool.ntp.org", "europe.pool.ntp.org"]
+  }
+)
+
+run_list(
+  "role[fr]"
+)
diff --git a/roles/ar.rb b/roles/ar.rb
new file mode 100644 (file)
index 0000000..ec8b086
--- /dev/null
@@ -0,0 +1,10 @@
+name "ar"
+description "Role applied to all servers located in Argentina"
+
+override_attributes(
+  :country => "ar"
+)
+
+run_list(
+  "role[base]"
+)
index dc3152f5442f04ff1167ba965cc0dc4b5e4fa33b..9cd93e053b7cbedcf23da576ff7686fdb41e0b81 100644 (file)
@@ -2,6 +2,9 @@ name "ascalon"
 description "Master role applied to ascalon"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "20g"
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -15,21 +18,21 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "16000 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "16384 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
   },
   :tilecache => {
-    :tile_parent => "montreal.render.openstreetmap.org",
-    :tile_siblings => [
-      "stormfly-02.openstreetmap.org",
-      "azure.openstreetmap.org",
-      "jakelong.openstreetmap.org"
-    ]
+    :tile_parent => "montreal.render.openstreetmap.org"
   }
 )
 
 run_list(
   "role[netalerts]",
-  "role[geodns]",
   "role[tilecache]"
 )
diff --git a/roles/aws.rb b/roles/aws.rb
deleted file mode 100644 (file)
index 5f4ac7a..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-name "aws"
-description "Role applied to all servers on AWS"
-
-default_attributes(
-  :hosted_by => "AWS",
-  :location => "Ireland",
-  :networking => {
-    :nameservers => ["172.31.0.2"],
-    :roles => {
-      :internal => {
-        :inet => {
-          :prefix => "20",
-          :gateway => "172.31.0.1"
-        }
-      },
-      :external => {
-        :zone => "aws",
-        :inet => {
-          :prefix => "32"
-        }
-      }
-    }
-  }
-)
-
-override_attributes(
-  :ntp => {
-    :servers => ["0.ie.pool.ntp.org", "1.ie.pool.ntp.org", "europe.pool.ntp.org"]
-  }
-)
-
-run_list(
-  "role[ie]"
-)
diff --git a/roles/azure.rb b/roles/azure.rb
deleted file mode 100644 (file)
index 8fa40d7..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-name "azure"
-description "Master role applied to azure"
-
-default_attributes(
-  :networking => {
-    :interfaces => {
-      :external_ipv4 => {
-        :interface => "bond0",
-        :role => :external,
-        :family => :inet,
-        :address => "204.16.246.252",
-        :prefix => "29",
-        :gateway => "204.16.246.249",
-        :bond => {
-          :mode => "802.3ad",
-          :slaves => %w[ens1f0 ens1f1]
-        }
-      },
-      :external_ipv6 => {
-        :interface => "bond0",
-        :role => :external,
-        :family => :inet6,
-        :address => "2607:fdc0:1::52",
-        :prefix => "64",
-        :gateway => "2607:fdc0:1::1"
-      }
-    }
-  },
-  :squid => {
-    :cache_mem => "5500 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
-  },
-  :tilecache => {
-    :tile_parent => "usa.render.openstreetmap.org",
-    :tile_siblings => []
-  }
-)
-
-run_list(
-  "role[teraswitch]",
-  "role[tilecache]"
-)
index b0c519bd8f3c3f1e0ac2c0cc893b55a967b5ee16..63ec1b1aae60ee421be78c1cc6afbd2ddc9a4c98 100644 (file)
@@ -2,11 +2,6 @@ name "backup"
 description "Role applied to backup.openstreetmap.org"
 
 default_attributes(
-  :accounts => {
-    :users => {
-      :osmbackup => { :status => :role }
-    }
-  },
   :rsyncd => {
     :modules => {
       :backup => {
@@ -28,10 +23,10 @@ default_attributes(
           "2001:41c9:2:d6::/64",                 # bytemark external
           "212.110.172.32",                      # shenron
           "2001:41c9:1:400::32",                 # shenron
-          "140.211.167.104",                     # osuosl
-          "140.211.167.105",                     # osuosl
-          "2605:bc80:3010:700::8cde:a768",       # osuosl
-          "2605:bc80:3010:700::8cde:a769",       # osuosl
+          "140.211.167.99",                      # osuosl
+          "140.211.167.100",                     # osuosl
+          "2605:bc80:3010:700::8cd3:a763",       # osuosl
+          "2605:bc80:3010:700::8cd3:a764",       # osuosl
           "127.0.0.0/8",                         # localhost
           "::1"                                  # localhost
         ]
index aa8f9977da33e189c3a78d1be3ac099c0ed1297f..e1ab5929b606bb66c928bb3f8030af4432c9ad20 100644 (file)
@@ -17,21 +17,41 @@ default_attributes(
       }
     }
   },
-  :squid => {
-    :cache_mem => "32000 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+  :postgresql => {
+    :settings => {
+      :defaults => {
+        :shared_buffers => "8GB",
+        :maintenance_work_mem => "7144MB",
+        :effective_cache_size => "16GB"
+      }
+    }
   },
-  :tilecache => {
-    :tile_parent => "melbourne.render.openstreetmap.org",
-    :tile_siblings => [
-      "waima.openstreetmap.org",
-      "tuatara.openstreetmap.org",
-      "longma.openstreetmap.org"
-    ]
+  :sysctl => {
+    :postgres => {
+      :comment => "Increase shared memory for postgres",
+      :parameters => {
+        "kernel.shmmax" => 9 * 1024 * 1024 * 1024,
+        "kernel.shmall" => 9 * 1024 * 1024 * 1024 / 4096
+      }
+    }
+  },
+  :tile => {
+    :database => {
+      :cluster => "12/main",
+      :postgis => "3"
+    },
+    :styles => {
+      :default => {
+        :tile_directories => [
+          { :name => "/store/tiles/default", :min_zoom => 0, :max_zoom => 19 }
+        ]
+      }
+    }
   }
 )
 
 run_list(
   "role[aarnet]",
-  "role[tilecache]"
+  "role[geodns]",
+  "role[tile]"
 )
index f9cb68efc411a5cc6591f35f6bd91034df1680d0..4d453e45ce32d779f0dc67fdfd83ecca58387d3c 100644 (file)
@@ -10,9 +10,6 @@ default_attributes(
       :jburgess => { :status => :administrator }
     }
   },
-  :apt => {
-    :sources => ["openstreetmap"]
-  },
   :munin => {
     :plugins => {
       :chrony => {
@@ -23,7 +20,7 @@ default_attributes(
   :networking => {
     :roles => {
       :internal => { :metric => 200, :zone => "loc" },
-      :external => { :metric => 100 }
+      :external => { :metric => 100, :zone => "osm" }
     },
     :search => ["openstreetmap.org"]
   },
@@ -44,9 +41,9 @@ default_attributes(
       :parameters => {
         "net.core.rmem_max" => "16777216",
         "net.core.wmem_max" => "16777216",
-        "net.ipv4.tcp_rmem" => "4096\t87380\t16777216",
-        "net.ipv4.tcp_wmem" => "4096\t65536\t16777216",
-        "net.ipv4.udp_mem" => "3145728\t4194304\t16777216"
+        "net.ipv4.tcp_rmem" => "4096 87380 16777216",
+        "net.ipv4.tcp_wmem" => "4096 65536 16777216",
+        "net.ipv4.udp_mem" => "3145728 4194304 16777216"
       }
     },
     :network_backlog => {
@@ -69,9 +66,10 @@ default_attributes(
       }
     },
     :default_qdisc => {
-      :comment => "Use pfifo_fast as the default queuing discipline",
+      :comment => "Use fq as the default queuing discipline and cubic for congestion control",
       :parameters => {
-        "net.core.default_qdisc" => "pfifo_fast"
+        "net.core.default_qdisc" => "fq",
+        "net.ipv4.tcp_congestion_control" => "cubic"
       }
     },
     :tune_cpu_scheduler => {
@@ -90,7 +88,8 @@ run_list(
   "recipe[chef]",
   "recipe[devices]",
   "recipe[hardware]",
-  "recipe[munin]",
+  "recipe[prometheus]",
+  "recipe[munin::plugins]",
   "recipe[networking]",
   "recipe[exim]",
   "recipe[ntp]",
index 835da71c93169bec8cc71cfb086d942c18d684d0..5d54e192790b055f434040b8ac90a4be22a2651a 100644 (file)
@@ -7,13 +7,5 @@ default_attributes(
       :blixadmin => { :status => :administrator }
     }
   },
-  :hosted_by => "Blix Solutions",
-  :networking => {
-    :nameservers => ["8.8.8.8", "8.8.4.4"],
-    :roles => {
-      :external => {
-        :zone => "bx"
-      }
-    }
-  }
+  :hosted_by => "Blix Solutions"
 )
index d0fcef8d3fbeb03a46b675cf831675ec66a317f1..00a976ab8edffb28bc5be3e6cddccc8aec085636 100644 (file)
@@ -2,6 +2,9 @@ name "boitata"
 description "Master role applied to boitata"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "14g"
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -23,17 +26,17 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "7500 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "8192 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
   },
   :tilecache => {
-    :tile_parent => "curitiba.render.openstreetmap.org",
-    :tile_siblings => [
-      "cherufe.openstreetmap.org",
-      "ascalon.openstreetmap.org",
-      "stormfly-02.openstreetmap.org",
-      "jakelong.openstreetmap.org"
-    ]
+    :tile_parent => "brazil.render.openstreetmap.org"
   }
 )
 
index ebee5e5d44b570f56a2e5c4722203a134862f6f9..9a30ff3cfd6aeff6da68298b9834fbbd2d0a16f6 100644 (file)
@@ -2,9 +2,6 @@ name "bowser"
 description "Master role applied to bowser"
 
 default_attributes(
-  :apt => {
-    :sources => ["postgresql"]
-  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -21,7 +18,6 @@ default_attributes(
     }
   },
   :postgresql => {
-    :versions => ["10"],
     :settings => {
       :defaults => {
         :shared_buffers => "8GB",
@@ -41,10 +37,9 @@ default_attributes(
   },
   :tile => {
     :database => {
-      :cluster => "10/main",
-      :postgis => "2.4"
+      :cluster => "12/main",
+      :postgis => "3"
     },
-    :node_file => "/store/database/nodes",
     :styles => {
       :default => {
         :tile_directories => [
index 2289df6484e929e6b16b80556bbe2c9ae675c78f..7b06247525ba718d57c0445ac17943cf50424e21 100644 (file)
@@ -5,12 +5,14 @@ default_attributes(
   :hosted_by => "Bytemark",
   :location => "York, England",
   :networking => {
-    :nameservers => ["10.0.32.20"],
     :roles => {
       :internal => {
         :inet => {
           :prefix => "20",
-          :gateway => "10.0.32.20"
+          :gateway => "10.0.32.20",
+          :routes => {
+            "10.0.0.0/8" => { :via => "10.0.32.20" }
+          }
         }
       },
       :external => {
@@ -35,6 +37,7 @@ default_attributes(
 
 override_attributes(
   :networking => {
+    :nameservers => ["10.0.32.20"],
     :search => ["bm.openstreetmap.org", "openstreetmap.org"]
   },
   :ntp => {
index 08708084e348800b1922c71c181bcf7b38849291..9b2bcc33f510fb8c8d261fcfe2025091f2bb10f1 100644 (file)
@@ -9,20 +9,18 @@ default_attributes(
   },
   :hosted_by => "Centro de Computação Científica e Software Livre, Universidade Federal do Paraná",
   :location => "Curitiba, Brazil",
-  :timezone => "America/Sao_Paulo",
   :networking => {
-    :nameservers => ["200.17.202.3", "200.236.31.1"],
-    :roles => {
-      :external => {
-        :zone => "osm"
-      }
-    }
-  }
+    :wireguard => { :keepalive => 180 }
+  },
+  :timezone => "America/Sao_Paulo"
 )
 
 override_attributes(
+  :networking => {
+    :nameservers => ["200.17.202.3", "200.236.31.1"]
+  },
   :ntp => {
-    :servers => ["0.br.pool.ntp.org", "1.br.pool.ntp.org", "america.pool.ntp.org"]
+    :servers => ["0.br.pool.ntp.org", "1.br.pool.ntp.org", "south-america.pool.ntp.org"]
   }
 )
 
index fab353fa680df20bf02b7c40eb7685e9865867e3..8ed5cb3f64bc602f3e91b02fdbec1b6d33795ba7 100644 (file)
@@ -7,14 +7,7 @@ default_attributes(
       :hbogner => { :status => :administrator }
     }
   },
-  :hosted_by => "CARNet",
-  :networking => {
-    :roles => {
-      :external => {
-        :zone => "cnt"
-      }
-    }
-  }
+  :hosted_by => "CARNet"
 )
 
 override_attributes(
diff --git a/roles/catalyst.rb b/roles/catalyst.rb
deleted file mode 100644 (file)
index edf3fad..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-name "catalyst"
-description "Role applied to all servers at Catalyst"
-
-default_attributes(
-  :hosted_by => "Catalyst",
-  :location => "Hamilton, New Zealand",
-  :networking => {
-    :nameservers => ["202.78.244.85", "202.78.244.86", "202.78.244.87"],
-    :roles => {
-      :external => {
-        :zone => "osm"
-      }
-    }
-  }
-)
-
-override_attributes(
-  :ntp => {
-    :servers => ["0.nz.pool.ntp.org", "1.nz.pool.ntp.org", "asia.pool.ntp.org"]
-  }
-)
-
-run_list(
-  "role[nz]"
-)
index df7fb7bc062fc9e8c04cdee27005f4d649ef836c..9d905a037b13713efbaf55e54fc2f308abf13463 100644 (file)
@@ -2,6 +2,9 @@ name "cherufe"
 description "Master role applied to cherufe"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "12g"
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -18,17 +21,24 @@ default_attributes(
     :port => 45222
   },
   :squid => {
-    :cache_mem => "6000 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "8192 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
+  },
+  :nginx => {
+    :cache => {
+      :proxy => {
+        :max_size => "8192M"
+      }
+    }
   },
   :tilecache => {
-    :tile_parent => "vinadelmar.render.openstreetmap.org",
-    :tile_siblings => [
-      "boitata.openstreetmap.org",
-      "ascalon.openstreetmap.org",
-      "stormfly-02.openstreetmap.org",
-      "jakelong.openstreetmap.org"
-    ]
+    :tile_parent => "vinadelmar.render.openstreetmap.org"
   }
 )
 
index 4bfe6513b5d0d97081edf0746537b437b7e8e004..ce4b9be22493c9c178ce39a51946ceba8a26632a 100644 (file)
@@ -2,6 +2,9 @@ name "chrysophylax"
 description "Master role applied to chrysophylax"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "14g"
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -23,16 +26,24 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "7500 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "10240 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
+  },
+  :nginx => {
+    :cache => {
+      :proxy => {
+        :max_size => "16384M"
+      }
+    }
   },
   :tilecache => {
-    :tile_parent => "zurich.render.openstreetmap.org",
-    :tile_siblings => [
-      "noomoahk.openstreetmap.org",
-      "ladon.openstreetmap.org",
-      "culebre.openstreetmap.org"
-    ]
+    :tile_parent => "zurich.render.openstreetmap.org"
   }
 )
 
index a876d8604a7f10a4378a981ce9984218794a9a27..5653d09c9c6e8c7f791cbd63ea6eacec6d5a4ccb 100644 (file)
@@ -2,6 +2,16 @@ name "cmok"
 description "Master role applied to cmok"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "6g"
+  },
+  :munin => {
+    :plugins => {
+      "diskstats_latency.sdd" => {
+        :avgrdwait => { :warning => "0:30" }
+      }
+    }
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -23,17 +33,17 @@ default_attributes(
     }
   },
   :squid => {
+    :version => 4,
     :cache_mem => "4096 MB",
-    :cache_dir => "coss /store/squid/coss-01 80000 block-size=8192 max-size=262144 membufs=80"
+    :cache_dir => [
+      "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
   },
   :tilecache => {
-    :tile_parent => "minsk.render.openstreetmap.org",
-    :tile_siblings => [
-      "katie.openstreetmap.org",
-      "konqi.openstreetmap.org",
-      "ridgeback.openstreetmap.org",
-      "gorynych.openstreetmap.org"
-    ]
+    :tile_parent => "minsk.render.openstreetmap.org"
   }
 )
 
diff --git a/roles/co.rb b/roles/co.rb
new file mode 100644 (file)
index 0000000..123288a
--- /dev/null
@@ -0,0 +1,11 @@
+name "co"
+description "Role applied to all servers located in Colombia"
+
+override_attributes(
+  :country => "co",
+  :timezone => "America/Bogota"
+)
+
+run_list(
+  "role[base]"
+)
index 7e255307baad6f9018191697b75181d0e9d918f4..5dfa89aaafa2e1d4c6ba49169dcf0b2a2d4964a6 100644 (file)
@@ -28,15 +28,6 @@ default_attributes(
       }
     },
     :trusted_users => ["www-data"]
-  },
-  :mysql => {
-    :settings => {
-      :mysqld => {
-        :innodb_strict_mode => true,
-        :innodb_file_per_table => true,
-        :innodb_file_format => "Barracuda"
-      }
-    }
   }
 )
 
diff --git a/roles/culebre.rb b/roles/culebre.rb
deleted file mode 100644 (file)
index b7e4fc8..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-name "culebre"
-description "Master role applied to culebre"
-
-default_attributes(
-  :networking => {
-    :interfaces => {
-      :external_ipv4 => {
-        :interface => "ens3",
-        :role => :external,
-        :family => :inet,
-        :address => "155.210.4.103",
-        :prefix => "28",
-        :gateway => "155.210.4.110"
-      },
-      :internal_ipv4 => {
-        :interface => "ens4",
-        :role => :internal,
-        :family => :inet,
-        :address => "10.148.97.151",
-        :prefix => "24"
-      }
-    }
-  },
-  :squid => {
-    :cache_mem => "12500 MB",
-    :cache_dir => "coss /store/squid/coss-01 80000 block-size=8192 max-size=262144 membufs=80"
-  },
-  :tilecache => {
-    :tile_parent => "zaragoza.render.openstreetmap.org",
-    :tile_siblings => [
-      "trogdor.openstreetmap.org",
-      "katie.openstreetmap.org",
-      "konqi.openstreetmap.org",
-      "gorynych.openstreetmap.org"
-    ]
-  }
-)
-
-run_list(
-  "role[unizar]",
-  "role[tilecache]"
-)
index 650c8a7fe5e09ebe76f4748b7a435e8a693f2f2c..d257382c6c4885d20922a4afa3bbefd27a7c0f3c 100644 (file)
@@ -8,19 +8,7 @@ default_attributes(
     }
   },
   :hosted_by => "DataHata",
-  :location => "Minsk, Belarus",
-  :networking => {
-    :nameservers => [
-      "31.130.200.2",
-      "8.8.8.8",
-      "8.8.4.4"
-    ],
-    :roles => {
-      :external => {
-        :zone => "dh"
-      }
-    }
-  }
+  :location => "Minsk, Belarus"
 )
 
 override_attributes(
index 3bfdbd7ca2fbccb9025176e1d3d82ea982f371de..11080f5ee98672a6d1c98254c6907bb0fcafb819 100644 (file)
@@ -3,14 +3,15 @@ description "Role applied to all the master database server"
 
 default_attributes(
   :postgresql => {
-    :versions => ["9.5"],
     :settings => {
       :defaults => {
-        :wal_level => "hot_standby",
+        :wal_level => "logical",
         :archive_mode => "on",
         :archive_command => "/usr/local/bin/openstreetmap-wal-e --terse wal-push %p",
         :max_wal_senders => "3",
+        :max_replication_slots => "1",
         :late_authentication_rules => [
+          { :database => "replication", :user => "replication", :address => "10.0.48.49/32" },
           { :database => "replication", :user => "replication", :address => "10.0.48.50/32" },
           { :database => "replication", :user => "replication", :address => "10.0.48.5/32" },
           { :database => "replication", :user => "replication", :address => "10.0.0.10/32" },
index 5b5c09b33fe85424d079bcb8200d1d09b07d1619..6fb2fd0b6ab20953c2c82ec599b6d088f9c1e7ee 100644 (file)
@@ -3,14 +3,13 @@ description "Role applied to all slave database servers"
 
 default_attributes(
   :postgresql => {
-    :versions => ["9.5"],
     :settings => {
       :defaults => {
         :hot_standby => "on",
         :hot_standby_feedback => "on",
         :standby_mode => "on",
         :primary_conninfo => {
-          :host => "karm.ams.openstreetmap.org",
+          :host => "snap-01.ams.openstreetmap.org",
           :port => "5432",
           :user => "replication",
           :passwords => { :bag => "db", :item => "passwords" }
index bb13e00c5d543b5332c0c5d64257e992fff52aed..bb567e240c2aedfd6a8170d1bc022482ef863aad 100644 (file)
@@ -39,7 +39,6 @@ default_attributes(
     "/store/rails" => { :host => "ironbelly", :path => "/store/rails" }
   },
   :postgresql => {
-    :versions => ["9.5"],
     :settings => {
       :defaults => {
         :listen_addresses => "*",
@@ -51,7 +50,6 @@ default_attributes(
         :cpu_tuple_cost => "0.1",
         :log_min_duration_statement => "1000",
         :late_authentication_rules => [
-          { :address => "10.0.16.0/20" },
           { :address => "10.0.32.0/20" },
           { :address => "10.0.48.0/20" }
         ]
diff --git a/roles/delta.rb b/roles/delta.rb
deleted file mode 100644 (file)
index 109c934..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-name "delta"
-description "Role applied to all servers at Delta Telecom"
-
-default_attributes(
-  :hosted_by => "Delta Telecom",
-  :location => "Baku, Azerbaijan",
-  :networking => {
-    :nameservers => ["94.20.20.20", "8.8.8.8", "8.8.4.4"],
-    :roles => {
-      :external => {
-        :zone => "dt"
-      }
-    }
-  }
-)
-
-override_attributes(
-  :ntp => {
-    :servers => ["0.az.pool.ntp.org", "1.az.pool.ntp.org", "europe.pool.ntp.org"]
-  }
-)
-
-run_list(
-  "role[az]"
-)
index 17b5c4726072897a5a0a114ca31cce6452c4d8b3..28305762642766c97b91d79f40bf639d99d0d187 100644 (file)
@@ -67,6 +67,8 @@ default_attributes(
       :mhohmann => { :status => :user },
       :enelson => { :status => :user },
       :gregrs => { :status => :user },
+      :stereo => { :status => :user },
+      :dmlu => { :status => :user },
       :ooc => {
         :status => :role,
         :members => [:tomh, :blackadder, :timsc, :ollie]
@@ -95,53 +97,54 @@ default_attributes(
       :max_connections_per_child => 10000
     }
   },
-  :apt => {
-    :sources => ["postgresql"]
-  },
   :dev => {
     :rails => {
       :master => {
         :repository => "https://git.openstreetmap.org/public/rails.git",
         :revision => "master",
-        :cgimap_repository => "git://github.com/zerebubuth/openstreetmap-cgimap.git",
+        :cgimap_repository => "https://github.com/zerebubuth/openstreetmap-cgimap.git",
         :cgimap_revision => "master",
         :aliases => ["api06.dev.openstreetmap.org"]
       },
       :tomh => {
-        :repository => "git://github.com/tomhughes/openstreetmap-website.git",
+        :repository => "https://github.com/tomhughes/openstreetmap-website.git",
         :revision => "next"
       },
       :comments => {
-        :repository => "git://github.com/ukasiu/openstreetmap-website.git",
+        :repository => "https://github.com/ukasiu/openstreetmap-website.git",
         :revision => "comments_list"
       },
       :locale => {
-        :repository => "git://github.com/tomhughes/openstreetmap-website.git",
+        :repository => "https://github.com/tomhughes/openstreetmap-website.git",
         :revision => "locale"
       },
+      :microcosms => {
+        :repository => "https://github.com/openbrian/osm-microcosms.git",
+        :revision => "microcosms"
+      },
       :upload => {
         :repository => "https://git.openstreetmap.org/public/rails.git",
         :revision => "master",
-        :cgimap_repository => "git://github.com/zerebubuth/openstreetmap-cgimap.git",
+        :cgimap_repository => "https://github.com/zerebubuth/openstreetmap-cgimap.git",
         :cgimap_revision => "feature/bulk_upload"
       }
     }
   },
   :postgresql => {
-    :versions => ["9.1", "9.5"],
+    :versions => ["12"],
     :settings => {
       :defaults => {
+        :max_connections => "500",
         :shared_buffers => "1GB",
         :work_mem => "32MB",
         :maintenance_work_mem => "64MB",
         :max_stack_depth => "4MB",
         :effective_cache_size => "4GB"
       },
-      "9.1" => {
-        :port => "5433"
-      },
-      "9.5" => {
-        :port => "5432"
+      "12" => {
+        :port => "5432",
+        :wal_level => "logical",
+        :max_replication_slots => "1"
       }
     }
   },
index 25ac17f00d2eb30ebfbedced23177de58766a525..c2af27b5895a809a3c2306f6f05aec7b2558aee2 100644 (file)
@@ -1,12 +1,6 @@
 name "dns"
 description "Role applied to DNS management servers"
 
-default_attributes(
-  :dns => {
-    :repository => "/var/lib/git/public/dns.git"
-  }
-)
-
 run_list(
   "recipe[dns]"
 )
index 6e5f2c614ebe601ea15765a46002082038707a90..a40547878e7d8dde9d6968542a4ae1d65ded3543 100644 (file)
@@ -1,17 +1,6 @@
 name "donate"
 description "Role applied to all donate servers"
 
-default_attributes(
-  :accounts => {
-    :users => {
-      :donate => {
-        :status => :role,
-        :members => [:grant, :tomh, :matt]
-      }
-    }
-  }
-)
-
 run_list(
   "recipe[donate]"
 )
diff --git a/roles/dotsrc.rb b/roles/dotsrc.rb
deleted file mode 100644 (file)
index e236f27..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-name "dotsrc"
-description "Role applied to all servers at dotsrc.org"
-
-default_attributes(
-  :hosted_by => "dotsrc.org",
-  :location => "Aalborg, Denmark",
-  :networking => {
-    :nameservers => [
-      "130.226.1.2",
-      "130.226.255.53",
-      "2001:878:0:100::2"
-    ],
-    :roles => {
-      :external => {
-        :zone => "ds"
-      }
-    }
-  }
-)
-
-override_attributes(
-  :ntp => {
-    :servers => ["0.dk.pool.ntp.org", "1.dk.pool.ntp.org", "europe.pool.ntp.org"]
-  }
-)
-
-run_list(
-  "role[dk]"
-)
index e26c7b5b4b3c4739def16d05764ccf6a5faa0819..8e4e50680d89a3d8c3bab5afe9f4f052dd83873c 100644 (file)
@@ -7,6 +7,9 @@ default_attributes(
       :zelja => { :status => :administrator }
     }
   },
+  :hardware => {
+    :shm_size => "18g"
+  },
   :location => "Osijek, Croatia",
   :networking => {
     :interfaces => {
@@ -26,21 +29,20 @@ default_attributes(
         :prefix => "64",
         :gateway => "fe80::161:53:30:97"
       }
-    },
-    :nameservers => [
-      "161.53.30.100",
-      "8.8.8.8"
-    ]
+    }
   },
   :squid => {
-    :cache_mem => "20000 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "16384 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
   },
   :tilecache => {
-    :tile_parent => "osijek.render.openstreetmap.org",
-    :tile_siblings => [
-      "viserion.openstreetmap.org"
-    ]
+    :tile_parent => "osijek.render.openstreetmap.org"
   }
 )
 
index 35c811f3533109f4a61f5fced107590cdfaf3ef2..98c938615378e8289ef4560400b2e7ef355b94d3 100644 (file)
@@ -10,7 +10,7 @@ default_attributes(
         :family => :inet,
         :address => "10.0.48.9",
         :bond => {
-          :slaves => %w[p18p1 p18p2]
+          :slaves => %w[ens18f0 ens18f1]
         }
       },
       :external_ipv4 => {
@@ -28,7 +28,7 @@ default_attributes(
     }
   },
   :postgresql => {
-    :versions => ["10"],
+    :versions => ["13"],
     :settings => {
       :defaults => {
         :work_mem => "300MB",
@@ -36,7 +36,7 @@ default_attributes(
         :random_page_cost => "1.5",
         :effective_cache_size => "60GB",
         :fsync => "on",
-        :effective_io_concurrency => "3"
+        :effective_io_concurrency => "500"
       }
     }
   },
@@ -45,8 +45,8 @@ default_attributes(
     :enable_backup => false,
     :enable_git_updates => true,
     :dbadmins => %w[lonvia tomh],
-    :dbcluster => "10/main",
-    :postgis => "2.4",
+    :dbcluster => "13/main",
+    :postgis => "3",
     :flatnode_file => "/ssd/nominatim/nodes.store",
     :logdir => "/ssd/nominatim/log",
     :tablespaces => {
index d900fbb4f41dfe7d1d0809cf6680d2f5596ffdf3..0dbe9dd0a7e9fec6dc0aebe123773674868b6ac1 100644 (file)
@@ -2,12 +2,6 @@ name "eddie"
 description "Master role applied to eddie"
 
 default_attributes(
-  :apt => {
-    :sources => ["postgresql"]
-  },
-  :db => {
-    :cluster => "9.5/main"
-  },
   :networking => {
     :interfaces => {
       :internal_ipv4 => {
diff --git a/roles/epix.rb b/roles/epix.rb
new file mode 100644 (file)
index 0000000..76b6de5
--- /dev/null
@@ -0,0 +1,17 @@
+name "epix"
+description "Role applied to all servers at EPIX"
+
+default_attributes(
+  :hosted_by => "EPIX",
+  :location => "Katowice, Poland"
+)
+
+override_attributes(
+  :ntp => {
+    :servers => ["0.pl.pool.ntp.org", "1.pl.pool.ntp.org", "europe.pool.ntp.org"]
+  }
+)
+
+run_list(
+  "role[pl]"
+)
index a35b4775c50b97526ad92825f812b937402d4396..e04f7fac5b253da09567e58567cda0af6757cf2d 100644 (file)
@@ -3,12 +3,14 @@ description "Role applied to all servers at Equinix"
 
 default_attributes(
   :networking => {
-    :nameservers => ["66.28.0.45", "66.28.0.61", "2001:978:1:1::d", "2001:978:1:2::d"],
     :roles => {
       :internal => {
         :inet => {
           :prefix => "20",
-          :gateway => "10.0.48.10"
+          :gateway => "10.0.48.10",
+          :routes => {
+            "10.0.0.0/8" => { :via => "10.0.48.10" }
+          }
         }
       },
       :external => {
@@ -19,7 +21,12 @@ default_attributes(
         },
         :inet6 => {
           :prefix => "64",
-          :gateway => "2001:978:2:2C::172:1"
+          :gateway => "2001:978:2:2C::172:1",
+          :routes => {
+            "2001:978:2:2c::/64" => { :type => "unreachable" },
+            "2001:4860::/32" => { :type => "unreachable" },
+            "2a00:1450:4000::/37" => { :type => "unreachable" }
+          }
         }
       }
     }
@@ -27,13 +34,14 @@ default_attributes(
   :web => {
     :backends => %w[rails1 rails2 rails3],
     :fileserver => "ironbelly",
-    :readonly_database_host => "karm.ams.openstreetmap.org",
+    :readonly_database_host => "snap-01.ams.openstreetmap.org",
     :primary_cluster => true
   }
 )
 
 override_attributes(
   :networking => {
+    :nameservers => ["66.28.0.45", "66.28.0.61"],
     :search => ["ams.openstreetmap.org", "openstreetmap.org"]
   },
   :ntp => {
diff --git a/roles/euserv.rb b/roles/euserv.rb
deleted file mode 100644 (file)
index 8a2de04..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-name "euserv"
-description "Role applied to all servers at EUserv"
-
-default_attributes(
-  :hosted_by => "EUserv",
-  :location => "Jena, Germany",
-  :networking => {
-    :nameservers => [
-      "85.31.184.60", "85.31.184.61", "85.31.185.60", "85.31.185.61"
-    ],
-    :roles => {
-      :external => {
-        :zone => "es"
-      }
-    }
-  }
-)
-
-override_attributes(
-  :ntp => {
-    :servers => ["0.de.pool.ntp.org", "1.de.pool.ntp.org", "europe.pool.ntp.org"]
-  }
-)
-
-run_list(
-  "role[de]"
-)
index ea1c0048161a117b6c24acebef058947cd16ddf3..93068a76c86a5653034c2d0c865628e1c6c0b454 100644 (file)
@@ -10,10 +10,8 @@ default_attributes(
   :hosted_by => "Exonetric",
   :location => "London, England",
   :networking => {
-    :nameservers => ["8.8.8.8", "8.8.4.4"],
     :roles => {
       :external => {
-        :zone => "ex",
         :inet => {
           :prefix => "28",
           :gateway => "178.250.74.33"
index 297a610c383b25f3dc576796e31be6aa336aafb9..c526226a845f107e80744d698e5a81bfa35ac94b 100644 (file)
@@ -2,6 +2,9 @@ name "fafnir"
 description "Master role applied to fafnir"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "36g"
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -23,17 +26,17 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "28000 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "32768 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
   },
   :tilecache => {
-    :tile_parent => "sweden.render.openstreetmap.org",
-    :tile_siblings => [
-      "nidhogg.openstreetmap.org",
-      "ridgeback.openstreetmap.org",
-      "rimfaxe.openstreetmap.org",
-      "trogdor.openstreetmap.org"
-    ]
+    :tile_parent => "sweden.render.openstreetmap.org"
   }
 )
 
diff --git a/roles/faimaison.rb b/roles/faimaison.rb
new file mode 100644 (file)
index 0000000..02ca7f3
--- /dev/null
@@ -0,0 +1,17 @@
+name "faimaison"
+description "Role applied to all servers at FAImaison"
+
+default_attributes(
+  :hosted_by => "FAImaison",
+  :location => "France"
+)
+
+override_attributes(
+  :ntp => {
+    :servers => ["0.fr.pool.ntp.org", "1.fr.pool.ntp.org", "europe.pool.ntp.org"]
+  }
+)
+
+run_list(
+  "role[fr]"
+)
index 7858e1b59b41e4bf6031154342064a7da386d0a3..96109c4436a4f077b05fc18940e6283740c3c9bd 100644 (file)
@@ -3,18 +3,7 @@ description "Role applied to all servers at Freifunk Rheinland"
 
 default_attributes(
   :hosted_by => "Freifunk Rheinland",
-  :location => "Berlin, Germany",
-  :networking => {
-    :nameservers => [
-      "8.8.8.8",
-      "8.8.4.4"
-    ],
-    :roles => {
-      :external => {
-        :zone => "ffr"
-      }
-    }
-  }
+  :location => "Berlin, Germany"
 )
 
 override_attributes(
index 58f78d3326727d0b7a5cbfa4c5271e36c9387e54..150f62d6fe089ac38531387faa55facabee017ad 100644 (file)
@@ -3,16 +3,12 @@ description "Role applied to all servers at Firefishy"
 
 default_attributes(
   :networking => {
-    :nameservers => ["8.8.8.8", "8.8.4.4"],
     :roles => {
       :internal => {
         :inet => {
           :prefix => "24",
           :gateway => "10.89.121.1"
         }
-      },
-      :external => {
-        :zone => "ff"
       }
     }
   }
diff --git a/roles/firnen.rb b/roles/firnen.rb
new file mode 100644 (file)
index 0000000..4bd2aff
--- /dev/null
@@ -0,0 +1,38 @@
+name "firnen"
+description "Master role applied to firnen"
+
+default_attributes(
+  :hardware => {
+    :shm_size => "36g"
+  },
+  :networking => {
+    :interfaces => {
+      :external_ipv4 => {
+        :interface => "enp6s0",
+        :role => :external,
+        :family => :inet,
+        :address => "188.241.28.82",
+        :prefix => "29",
+        :gateway => "188.241.28.81"
+      }
+    }
+  },
+  :squid => {
+    :version => 4,
+    :cache_mem => "32768 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
+  },
+  :tilecache => {
+    :tile_parent => "germany.render.openstreetmap.org"
+  }
+)
+
+run_list(
+  "role[epix]",
+  "role[tilecache]"
+)
index e9a38146ab28be895cff281fd2d179e8c3a442e8..0eec150b006e35b5461bab07979e538ca2619933 100644 (file)
@@ -2,26 +2,15 @@ name "forum"
 description "Role applied to all forum servers"
 
 default_attributes(
-  :accounts => {
-    :users => {
-      :lambertus => {
-        :status => :administrator
-      },
-      :forum => {
-        :status => :role,
-        :members => [:lambertus, :grant]
-      }
-    }
-  },
   :apache => {
-    :mpm => "prefork",
+    :mpm => "event",
     :timeout => 60,
-    :keepalive => false,
-    :prefork => {
-      :start_servers => 20,
-      :min_spare_servers => 20,
-      :max_spare_servers => 50,
-      :max_request_workers => 256
+    :event => {
+      :server_limit => 18,
+      :max_request_workers => 450,
+      :min_spare_threads => 50,
+      :max_spare_threads => 150,
+      :listen_cores_buckets_ratio => 4
     }
   }
 )
index 9a2c2e553837c30fda36b4e030a889d73c2051aa..9328d2688aff2803bacc14fe20a62c9d464c4049 100644 (file)
@@ -2,16 +2,11 @@ name "foundation"
 description "Role applied to all OSMF servers"
 
 default_attributes(
-  :apache => {
-    :mpm => "prefork",
-    :timeout => 60,
-    :keepalive => false
-  },
   :apt => {
     :sources => ["passenger"]
   },
   :elasticsearch => {
-    :version => "5.x",
+    :version => "6.x",
     :cluster => {
       :name => "foundation"
     }
index e827205977b0f98f8eb0532b809cf602d73c74b7..a9cca6869bfb30bce1249f769c3f5f57fb81473b 100644 (file)
@@ -6,6 +6,7 @@ default_attributes(
     :shm_size => "6g"
   },
   :networking => {
+    :hostname => "seshat.civ.zcu.cz",
     :interfaces => {
       :external_ipv4 => {
         :interface => "ens3",
@@ -28,13 +29,7 @@ default_attributes(
     ]
   },
   :tilecache => {
-    :tile_parent => "pilsen.render.openstreetmap.org",
-    :tile_siblings => [
-      "sarkany.openstreetmap.org",
-      "chrysophylax.openstreetmap.org",
-      "drogon.openstreetmap.org",
-      "viserion.openstreetmap.org"
-    ]
+    :tile_parent => "czechia.render.openstreetmap.org"
   }
 )
 
diff --git a/roles/g5solutions.rb b/roles/g5solutions.rb
deleted file mode 100644 (file)
index 5cb41ec..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-name "g5solutions"
-description "Role applied to all servers at G5 Solutions"
-
-default_attributes(
-  :accounts => {
-    :users => {
-      :g5team => { :status => :administrator }
-    }
-  },
-  :hosted_by => "G5 Solutions",
-  :location => "Indonesia",
-  :networking => {
-    :nameservers => [
-      "8.8.8.8",
-      "8.8.4.4"
-    ],
-    :roles => {
-      :external => {
-        :zone => "g5s"
-      }
-    }
-  }
-)
-
-override_attributes(
-  :ntp => {
-    :servers => ["0.id.pool.ntp.org", "1.id.pool.ntp.org", "asia.pool.ntp.org"]
-  }
-)
-
-run_list(
-  "role[id]"
-)
diff --git a/roles/gandi.rb b/roles/gandi.rb
new file mode 100644 (file)
index 0000000..2fcd108
--- /dev/null
@@ -0,0 +1,20 @@
+name "gandi"
+description "Role applied to all servers at Gandi"
+
+default_attributes(
+  :hosted_by => "Gandi",
+  :location => "Bissen, Luxembourg"
+)
+
+override_attributes(
+  :networking => {
+    :nameservers => ["217.70.186.194", "217.70.186.193", "2001:4b98:dc2:49::193"]
+  },
+  :ntp => {
+    :servers => ["0.lu.pool.ntp.org", "1.lu.pool.ntp.org", "europe.pool.ntp.org"]
+  }
+)
+
+run_list(
+  "role[lu]"
+)
index 517940543ebd74d4aaa157d42c678d0c6836eecf..c57c56e0f871920edac5826f63b7cbec3ed17c38 100644 (file)
@@ -2,6 +2,12 @@ name "gorynych"
 description "Master role applied to gorynych"
 
 default_attributes(
+  :hardware => {
+    :ipmi => {
+      :excluded_sensors => [3, 4]
+    },
+    :shm_size => "20g"
+  },
   :munin => {
     :plugins => {
       :smart_sdc => {
@@ -42,15 +48,25 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "5800 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "16384 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
+  },
+  :nginx => {
+    :cache => {
+      :proxy => {
+        :directory => "/store/nginx-cache/proxy-cache",
+        :max_size => "32768M"
+      }
+    }
   },
   :tilecache => {
-    :tile_parent => "moscow.render.openstreetmap.org",
-    :tile_siblings => [
-      "noomoahk.openstreetmap.org",
-      "cmok.openstreetmap.org"
-    ]
+    :tile_parent => "moscow.render.openstreetmap.org"
   }
 )
 
index 285d461de69cea0ed216758151eda7cec42a8ebb..e6a0e5ec2f340fd1001c85bac26b5117bf1a531c 100644 (file)
@@ -6,7 +6,6 @@ default_attributes(
     :users => {
       :enf => { :status => :administrator },
       :gpstile => {
-        :status => :role,
         :members => [:enf, :tomh]
       }
     }
@@ -25,6 +24,5 @@ default_attributes(
 )
 
 run_list(
-  "recipe[memcached]",
   "recipe[gps-tile]"
 )
diff --git a/roles/greenmini.rb b/roles/greenmini.rb
new file mode 100644 (file)
index 0000000..2156eb3
--- /dev/null
@@ -0,0 +1,25 @@
+name "greenmini"
+description "Role applied to all servers at greenminihost"
+
+default_attributes(
+  :accounts => {
+    :users => {
+      :joris => { :status => :administrator }
+    }
+  },
+  :hosted_by => "greenminihost",
+  :location => "Dronten, Netherlands"
+)
+
+override_attributes(
+  :networking => {
+    :nameservers => ["45.148.169.130", "185.200.102.102", "2a0a:aa42:222:2500::2500", "2a0a:aa42:321:2000::53"]
+  },
+  :ntp => {
+    :servers => ["0.nl.pool.ntp.org", "1.nl.pool.ntp.org", "europe.pool.ntp.org"]
+  }
+)
+
+run_list(
+  "role[nl]"
+)
index 054af06f1a686a5a6ef3b6ce0d0b4a5ddda43134..e7bf0b295a5e297b12e5ed9a0ad1eb67ed4b9497 100644 (file)
@@ -28,12 +28,6 @@ default_attributes(
           :connection_limit => "-"
         }
       ]
-    },
-    :nameservers => ["2a00:5884::7", "8.8.8.8", "8.8.4.4"],
-    :roles => {
-      :external => {
-        :zone => "grf"
-      }
     }
   }
 )
index 2d78c10b79b6ca43027f9d6000e6ba59b85c18f1..349cc2627caf79c49bf7876cec547f7db75c4620 100644 (file)
@@ -5,13 +5,13 @@ default_attributes(
   :networking => {
     :interfaces => {
       :internal_ipv4 => {
-        :interface => "em1.2801",
+        :interface => "enp3s0f0.2801",
         :role => :internal,
         :family => :inet,
         :address => "10.0.0.19"
       },
       :external_ipv4 => {
-        :interface => "em1.2800",
+        :interface => "enp3s0f0.2800",
         :role => :external,
         :family => :inet,
         :address => "193.60.236.15"
index 8e177a8ff49ea2781610271c2015f8c0236587d8..b260ff89598a47378c113f16da012ce30e93e48e 100644 (file)
@@ -13,7 +13,7 @@ default_attributes(
         :family => :inet,
         :address => "10.0.32.20",
         :bond => {
-          :slaves => %w[em1 em2]
+          :slaves => %w[enp2s0f0 enp2s0f1]
         }
       },
       :external_ipv4 => {
@@ -30,32 +30,6 @@ default_attributes(
       }
     }
   },
-  :openvpn => {
-    :address => "10.0.16.5",
-    :tunnels => {
-      :ic2bm => {
-        :port => "1194",
-        :mode => "server",
-        :peer => {
-          :host => "ironbelly.openstreetmap.org"
-        }
-      },
-      :aws2bm => {
-        :port => "1195",
-        :mode => "server",
-        :peer => {
-          :host => "fafnir.openstreetmap.org"
-        }
-      },
-      :ucl2bm => {
-        :port => "1196",
-        :mode => "server",
-        :peer => {
-          :host => "ridley.openstreetmap.org"
-        }
-      }
-    }
-  },
   :planet => {
     :replication => "disabled"
   }
@@ -67,7 +41,6 @@ run_list(
   "role[gateway]",
   "role[web-storage]",
   "role[backup]",
-  "role[planet]",
-  # "role[planetdump]",
-  "recipe[openvpn]"
+  "role[planet]"
+  # "role[planetdump]"
 )
index 6893b6592088f95765cf728cfdf22dacb1217051..a08d1841d178572a1c1053c7671ee75c9f1a2ce4 100644 (file)
@@ -8,18 +8,7 @@ default_attributes(
     }
   },
   :hosted_by => "GRNET",
-  :location => "Athens, Greece",
-  :networking => {
-    :nameservers => [
-      "8.8.8.8",
-      "8.8.4.4"
-    ],
-    :roles => {
-      :external => {
-        :zone => "grn"
-      }
-    }
-  }
+  :location => "Athens, Greece"
 )
 
 override_attributes(
index 4ed08654daa0a19776575884b7008f9b8f6c0832..4948c8d6c51d470489be84cf381cbfa8db681d02 100644 (file)
@@ -2,7 +2,10 @@ name "hetzner"
 description "Role applied to all servers at Hetzner"
 
 default_attributes(
-  :hosted_by => "Hetzner",
+  :hosted_by => "Hetzner"
+)
+
+override_attributes(
   :networking => {
     :nameservers => [
       "213.133.98.98",
@@ -11,16 +14,8 @@ default_attributes(
       "2a01:4f8:0:a111::add:9898",
       "2a01:4f8:0:a102::add:9999",
       "2a01:4f8:0:a0a1::add:1010"
-    ],
-    :roles => {
-      :external => {
-        :zone => "hz"
-      }
-    }
-  }
-)
-
-override_attributes(
+    ]
+  },
   :ntp => {
     :servers => ["0.de.pool.ntp.org", "1.de.pool.ntp.org", "europe.pool.ntp.org"]
   }
diff --git a/roles/hostedinnz.rb b/roles/hostedinnz.rb
deleted file mode 100644 (file)
index ef24387..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-name "hostedinnz"
-description "Role applied to all servers at HostedIn.NZ"
-
-default_attributes(
-  :accounts => {
-    :users => {
-      :asmith => { :status => :administrator }
-    }
-  },
-  :hosted_by => "HostedIn.NZ",
-  :location => "Wellington, New Zealand",
-  :networking => {
-    :nameservers => ["8.8.8.8", "8.8.4.4"],
-    :roles => {
-      :external => {
-        :zone => "osm"
-      }
-    }
-  },
-  :snmpd => {
-    :clients => ["103.106.66.28"],
-    :community => "hostedinnz",
-    :location => "Wellington"
-  }
-)
-
-override_attributes(
-  :ntp => {
-    :servers => ["0.nz.pool.ntp.org", "1.nz.pool.ntp.org", "asia.pool.ntp.org"]
-  }
-)
-
-run_list(
-  "role[nz]",
-  "recipe[snmpd]"
-)
index 3f0cfd6004f04b72e7574bf9fd236c9eec0c92f6..0c27aca8ef86744f154820eb44a96626552b7abb 100644 (file)
@@ -4,6 +4,12 @@ description "Role applied to all HP DL360 G6 machines"
 default_attributes(
   :munin => {
     :plugins => {
+      :hpasmcli2_fans => {
+        :fan1 => { :warning => "85", :critical => "90" },
+        :fan2 => { :warning => "85", :critical => "90" },
+        :fan3 => { :warning => "85", :critical => "90" },
+        :fan4 => { :warning => "85", :critical => "90" }
+      },
       :ipmi_temp => {
         :Temp1 => { :label => "External Environment" },
         :Temp2 => { :warning => ":", :label => "CPU 1" },
index fedd79afc43b7fbd21aa79780b229113f1cc0a40..3cc42a71862aa892e9530364090fae7384f2db7d 100644 (file)
@@ -4,16 +4,15 @@ description "Role applied to all imagery servers"
 default_attributes(
   :accounts => {
     :users => {
+      :dmlu => { :status => :user },
       :htonl => { :status => :user },
+      :stereo => { :status => :user },
       :imagery => {
         :status => :role,
-        :members => [:grant, :tomh, :htonl]
+        :members => [:grant, :tomh, :dmlu, :htonl, :stereo ]
       }
     }
   },
-  :apt => {
-    :sources => %w[nginx ubuntugis-unstable]
-  },
   :sysctl => {
     :sockets => {
       :comment => "Increase size of connection queue",
@@ -27,12 +26,6 @@ default_attributes(
         "kernel.sched_min_granularity_ns" => 10000000,
         "kernel.sched_wakeup_granularity_ns" => 15000000
       }
-    },
-    :kernel_tfo_listen_enable => {
-      :comment => "Enable TCP Fast Open for listening sockets",
-      :parameters => {
-        "net.ipv4.tcp_fastopen" => 3
-      }
     }
   },
   :nginx => {
@@ -55,5 +48,7 @@ run_list(
   "recipe[imagery::gb_surrey_aerial]",
   "recipe[imagery::za_ngi_topo]",
   "recipe[imagery::za_coct_aerial]",
-  "recipe[imagery::na_sgswa_topo]"
+  "recipe[imagery::na_sgswa_topo]",
+  "recipe[imagery::lu_ngl_dtm]",
+  "recipe[imagery::lu_lidar_hillshade]"
 )
index 03d5ff70e4cb998a02c4e661637a4120b7bcc6d1..96dd61a960a9584fd929d78ba91fb03d9cb77922 100644 (file)
@@ -3,22 +3,13 @@ description "Role applied to all servers at INX-ZA"
 
 default_attributes(
   :hosted_by => "INX-ZA",
-  :location => "Cape Town, South Africa",
-  :networking => {
-    :nameservers => [
-      "196.10.52.52",
-      "196.10.54.54",
-      "196.10.55.55"
-    ],
-    :roles => {
-      :external => {
-        :zone => "ixz"
-      }
-    }
-  }
+  :location => "Cape Town, South Africa"
 )
 
 override_attributes(
+  :networking => {
+    :nameservers => ["196.10.52.52", "196.10.54.54", "196.10.55.55"]
+  },
   :ntp => {
     :servers => ["0.za.pool.ntp.org", "1.za.pool.ntp.org", "africa.pool.ntp.org"]
   }
index f12e2691e9d0be208d120df607764f5bcbcb5934..732542e69a0350cc3460e6d1033336a97eecd0f8 100644 (file)
@@ -2,5 +2,5 @@ name "irc"
 description "Role applied to all IRC gateways"
 
 run_list(
-  "recipe[cgiirc]"
+  "recipe[irc]"
 )
index 2f05572fb1009330586ea4db84ffbe34f1ef5494..ad5ea034b8fdda92c1d35a9dce339d4c1f54c1a2 100644 (file)
@@ -55,36 +55,16 @@ default_attributes(
       }
     }
   },
-  :openvpn => {
-    :address => "10.0.16.2",
-    :tunnels => {
-      :ic2ucl => {
-        :port => "1194",
-        :mode => "server",
-        :peer => {
-          :host => "ridley.openstreetmap.org"
-        }
-      },
-      :aws2ic => {
-        :port => "1195",
-        :mode => "server",
-        :peer => {
-          :host => "fafnir.openstreetmap.org"
-        }
-      },
-      :ic2bm => {
-        :port => "1196",
-        :mode => "client",
-        :peer => {
-          :host => "grisu.openstreetmap.org",
-          :port => "1194"
-        }
-      }
-    }
-  },
   :planet => {
     :replication => "enabled"
   },
+  :prometheus => {
+    :snmp => {
+      "pdu1" => { :address => "10.0.48.100", :module => "apcups", :labels => { "site" => "amsterdam" } },
+      "pdu2" => { :address => "10.0.48.101", :module => "apcups", :labels => { "site" => "amsterdam" } },
+      "switch1" => { :address => "130.117.76.2", :module => "if_mib", :labels => { "site" => "amsterdam" } }
+    }
+  },
   :rsyncd => {
     :modules => {
       :hosts => {
@@ -136,9 +116,7 @@ run_list(
   "role[backup]",
   "role[planet]",
   "role[planetdump]",
-  "role[logstash]",
   "recipe[rsyncd]",
   "recipe[dhcpd]",
-  "recipe[openvpn]",
   "recipe[tilelog]"
 )
index b734f2eea022aeed11b4576ea1b95471e6bec9b9..094f92b0b6b76288bfbec2ddab4966ba071a5514 100644 (file)
@@ -23,12 +23,6 @@ default_attributes(
           :connection_limit => "-"
         }
       ]
-    },
-    :nameservers => ["2001:8e0:ffff:ac1::1", "8.8.8.8", "8.8.4.4"],
-    :roles => {
-      :external => {
-        :zone => "osm"
-      }
     }
   }
 )
diff --git a/roles/jakelong.rb b/roles/jakelong.rb
deleted file mode 100644 (file)
index 8839b48..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-name "jakelong"
-description "Master role applied to jakelong"
-
-default_attributes(
-  :networking => {
-    :interfaces => {
-      :external_ipv4 => {
-        :interface => "eth0",
-        :role => :external,
-        :family => :inet,
-        :address => "71.19.155.177",
-        :prefix => "24",
-        :gateway => "71.19.155.1"
-      },
-      :external_ipv6 => {
-        :interface => "eth0",
-        :role => :external,
-        :family => :inet6,
-        :address => "2605:2700:0:17:a800:ff:fe3e:cdca",
-        :prefix => "64",
-        :gateway => "2605:2700:0:17::1"
-      }
-    }
-  },
-  :squid => {
-    :cache_mem => "1024 MB",
-    :cache_dir => "coss /store/squid/coss-01 24000 block-size=8192 max-size=262144 membufs=30"
-  },
-  :sysctl => {
-    :kvm => {
-      :comment => "Tuning for KVM guest",
-      :parameters => {
-        "kernel.sched_min_granularity_ns" => 10000000,
-        "kernel.sched_wakeup_granularity_ns" => 15000000
-      }
-    },
-    :network_conntrack_max => {
-      :comment => "Increase max number of connections tracked",
-      :parameters => {
-        "net.netfilter.nf_conntrack_max" => "65536"
-      }
-    }
-  },
-  :tilecache => {
-    :tile_parent => "sanfrancisco.render.openstreetmap.org",
-    :tile_siblings => [
-      "stormfly-02.openstreetmap.org",
-      "azure.openstreetmap.org",
-      "ascalon.openstreetmap.org",
-      "katie.openstreetmap.org",
-      "konqi.openstreetmap.org"
-    ]
-  }
-)
-
-run_list(
-  "role[prgmr]",
-  "role[geodns]",
-  "role[tilecache]"
-)
index 9a026f370f542bdf3b93c40db77334bd5011c79b..eb24ced21e3c60cbd00c91dac8a9780db84316c1 100644 (file)
@@ -3,23 +3,13 @@ description "Role applied to all servers at Jump Networks"
 
 default_attributes(
   :hosted_by => "Jump Networks",
-  :location => "London, England",
-  :networking => {
-    :nameservers => [
-      "185.73.44.3",
-      "2001:ba8:0:2c02::",
-      "2001:ba8:0:2c03::",
-      "2001:ba8:0:2c04::"
-    ],
-    :roles => {
-      :external => {
-        :zone => "jn"
-      }
-    }
-  }
+  :location => "London, England"
 )
 
 override_attributes(
+  :networking => {
+    :nameservers => ["185.73.44.3", "2001:ba8:0:2c02::", "2001:ba8:0:2c03::", "2001:ba8:0:2c04::"]
+  },
   :ntp => {
     :servers => ["0.uk.pool.ntp.org", "1.uk.pool.ntp.org", "europe.pool.ntp.org"]
   }
index 953496dfac4c3fcd8129eb63248eaaa54681f93f..1a094e65e4e8b8b4a186b401680323d420bf769e 100644 (file)
@@ -2,6 +2,9 @@ name "kalessin"
 description "Master role applied to kalessin"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "20g"
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -23,21 +26,29 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "12500 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "16384 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
+  },
+  :nginx => {
+    :cache => {
+      :proxy => {
+        :keys_zone => "proxy_cache_zone:64M",
+        :max_size => "2048M"
+      }
+    }
   },
   :tilecache => {
-    :tile_parent => "germany.render.openstreetmap.org",
-    :tile_siblings => [
-      "katie.openstreetmap.org",
-      "konqi.openstreetmap.org",
-      "keizer.openstreetmap.org"
-    ]
+    :tile_parent => "germany.render.openstreetmap.org"
   }
 )
 
 run_list(
   "role[ffrl]",
-  "role[geodns]",
   "role[tilecache]"
 )
index 8f0ce7a234de14536cf422a0bbc8028ad677c389..04b5a925be475beef37f241c1d3c8f714290a23c 100644 (file)
@@ -2,12 +2,6 @@ name "karm"
 description "Master role applied to karm"
 
 default_attributes(
-  :apt => {
-    :sources => ["postgresql"]
-  },
-  :db => {
-    :cluster => "9.5/main"
-  },
   :networking => {
     :interfaces => {
       :internal_ipv4 => {
@@ -16,7 +10,7 @@ default_attributes(
         :family => :inet,
         :address => "10.0.48.50",
         :bond => {
-          :slaves => %w[enp1s0f0 enp1s0f1]
+          :slaves => %w[enp1s0f0 enp1s0f1 enp2s0f0 enp2s0f1]
         }
       }
     }
@@ -46,6 +40,5 @@ default_attributes(
 
 run_list(
   "role[equinix]",
-  "role[db-master]",
-  "role[db-backup]"
+  "role[db-slave]"
 )
diff --git a/roles/katie.rb b/roles/katie.rb
deleted file mode 100644 (file)
index f387555..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-name "katie"
-description "Master role applied to katie"
-
-default_attributes(
-  :devices => {
-    :disktune => {
-      :comment => "Tune scheduler for Toshiba disks",
-      :type => "block",
-      :bus => "ata",
-      :serial => "TOSHIBA_DT01ACA300_*",
-      :attrs => {
-        "queue/scheduler" => "deadline"
-      }
-    }
-  },
-  :location => "Falkenstein, Germany",
-  :networking => {
-    :interfaces => {
-      :external_ipv4 => {
-        :interface => "eth0",
-        :role => :external,
-        :family => :inet,
-        :address => "144.76.70.77",
-        :prefix => "27",
-        :gateway => "144.76.70.65"
-      },
-      :external_ipv6 => {
-        :interface => "eth0",
-        :role => :external,
-        :family => :inet6,
-        :address => "2a01:4f8:191:834c::2",
-        :prefix => "64",
-        :gateway => "fe80::1"
-      }
-    }
-  },
-  :squid => {
-    :cache_mem => "12500 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
-  },
-  :tilecache => {
-    :tile_parent => "germany.render.openstreetmap.org",
-    :tile_siblings => [
-      "konqi.openstreetmap.org",
-      "keizer.openstreetmap.org"
-    ]
-  }
-)
-
-run_list(
-  "role[hetzner]",
-  "role[geodns]",
-  "role[tilecache]"
-)
index 1e471b04099e2c6737c1da56884f8a973b03e198..6143cf533a3e1565a6e25b779d8a432e22ec89c9 100644 (file)
@@ -2,12 +2,6 @@ name "katla"
 description "Master role applied to katla"
 
 default_attributes(
-  :apt => {
-    :sources => ["postgresql"]
-  },
-  :db => {
-    :cluster => "9.5/main"
-  },
   :devices => {
     :store_slow => {
       :comment => "RAID array mounted on /store/arrays/slow",
index 9bb3e2eb0f5c3ddfd93cd45e0b07850cb33afc01..3ce0de1abd38367715d94b6f55b70f15d4e51f6b 100644 (file)
@@ -2,6 +2,9 @@ name "keizer"
 description "Master role applied to keizer"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "12g"
+  },
   :location => "Nuremberg, Germany",
   :networking => {
     :interfaces => {
@@ -24,15 +27,17 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "7500 MB",
-    :cache_dir => "coss /store/squid/coss-01 80000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "8192 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
   },
   :tilecache => {
-    :tile_parent => "germany.render.openstreetmap.org",
-    :tile_siblings => [
-      "katie.openstreetmap.org",
-      "konqi.openstreetmap.org"
-    ]
+    :tile_parent => "germany.render.openstreetmap.org"
   }
 )
 
index 941e9b2b232309fae03c5d1e59d87dffddcd0441..5a3ff94b51c027c9429431c6c1486108982a5497 100644 (file)
@@ -23,14 +23,14 @@ default_attributes(
   :networking => {
     :interfaces => {
       :external_ipv4 => {
-        :interface => "em1",
+        :interface => "enp2s0f0",
         :role => :external,
         :family => :inet,
         :address => "178.250.74.36",
         :hwaddress => "d8:d3:85:5d:87:5e"
       },
       :external_ipv6 => {
-        :interface => "em1",
+        :interface => "enp2s0f0",
         :role => :external,
         :family => :inet6,
         :address => "2a02:1658:4:0:dad3:85ff:fe5d:875e",
index 6198120cfd7c65f680a4923fc97a0c95ce403b11..d45d4e53f9e2a3421710f6bb5bd4709022e60f26 100644 (file)
@@ -1,14 +1,6 @@
 name "kibana"
 description "Role applied to all kibana servers"
 
-default_attributes(
-  :accounts => {
-    :users => {
-      :kibana => { :status => :role }
-    }
-  }
-)
-
 run_list(
   "recipe[kibana]"
 )
diff --git a/roles/kokosnuss.rb b/roles/kokosnuss.rb
new file mode 100644 (file)
index 0000000..cebe596
--- /dev/null
@@ -0,0 +1,41 @@
+name "kokosnuss"
+description "Master role applied to kokosnuss"
+
+default_attributes(
+  :hardware => {
+    :shm_size => "12g"
+  },
+  :networking => {
+    :interfaces => {
+      :external_ipv4 => {
+        :interface => "venet0",
+        :role => :external,
+        :family => :inet,
+        :address => "85.214.255.86",
+        :prefix => "32",
+        :gateway => "85.214.255.86"
+      }
+    },
+    :wireguard => {
+      :enabled => false
+    }
+  },
+  :squid => {
+    :version => 4,
+    :cache_mem => "8192 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
+  },
+  :tilecache => {
+    :tile_parent => "germany.render.openstreetmap.org"
+  }
+)
+
+run_list(
+  "role[strato]",
+  "role[tilecache]"
+)
diff --git a/roles/konqi.rb b/roles/konqi.rb
deleted file mode 100644 (file)
index fda937f..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-name "konqi"
-description "Master role applied to konqi"
-
-default_attributes(
-  :networking => {
-    :interfaces => {
-      :external_ipv4 => {
-        :interface => "eth0",
-        :role => :external,
-        :family => :inet,
-        :address => "81.7.11.83",
-        :prefix => "24",
-        :gateway => "81.7.11.1"
-      },
-      :external_ipv6 => {
-        :interface => "eth0",
-        :role => :external,
-        :family => :inet6,
-        :address => "2a02:180:1:1::517:b53",
-        :prefix => "64",
-        :gateway => "2a02:180:1:1::1"
-      }
-    }
-  },
-  :squid => {
-    :cache_mem => "12500 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
-  },
-  :tilecache => {
-    :tile_parent => "germany.render.openstreetmap.org",
-    :tile_siblings => [
-      "katie.openstreetmap.org",
-      "trogdor.openstreetmap.org",
-      "ridgeback.openstreetmap.org",
-      "gorynych.openstreetmap.org",
-      "simurgh.openstreetmap.org"
-    ]
-  }
-)
-
-run_list(
-  "role[euserv]",
-  "role[tilecache]"
-)
index 75da422c89adeb73a825be5fb7e526293791d84d..c777bc6700221da7a7e6d5de784bee97628ca70a 100644 (file)
@@ -2,6 +2,9 @@ name "ladon"
 description "Master role applied to ladon"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "36g"
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -15,7 +18,7 @@ default_attributes(
           :mode => "802.3ad",
           :miimon => "100",
           :xmithashpolicy => "layer3+4",
-          :slaves => %w[eth0 eth1]
+          :slaves => %w[ens1f0 ens1f1]
         }
       },
       :external_ipv6 => {
@@ -29,18 +32,17 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "6100 MB",
-    :cache_dir => "coss /store/squid/coss-01 80000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "32768 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
   },
   :tilecache => {
-    :tile_parent => "athens.render.openstreetmap.org",
-    :tile_siblings => [
-      "trogdor.openstreetmap.org",
-      "katie.openstreetmap.org",
-      "konqi.openstreetmap.org",
-      "ridgeback.openstreetmap.org",
-      "gorynych.openstreetmap.org"
-    ]
+    :tile_parent => "athens.render.openstreetmap.org"
   }
 )
 
index c0b389da90aa2a3eba8b2a4e7b5815f967d6ceb8..3c96b90ae18a589b72119b0476c2b1e3565e2e71 100644 (file)
@@ -1,16 +1,6 @@
 name "letsencrypt"
 description "Role applied to all letsencrypt servers"
 
-default_attributes(
-  :accounts => {
-    :users => {
-      :letsencrypt => {
-        :status => :role
-      }
-    }
-  }
-)
-
 run_list(
   "recipe[letsencrypt]"
 )
index 60b34a31189107fe906b3326d28ee3dad47d08b0..cf7e7461b8f36d415b28b17e223be94aae0f14e9 100644 (file)
@@ -3,7 +3,7 @@ description "Role applied to all logstash forwarders"
 
 default_attributes(
   :apt => {
-    :sources => ["elasticsearch5.x"]
+    :sources => ["elasticsearch6.x"]
   }
 )
 
index 9e421fc8d2ad5ec7eb7ef53334684df6eec242e6..b5cbac83630910bb098a2a944afa92d9d7c38ae1 100644 (file)
@@ -2,12 +2,6 @@ name "logstash"
 description "Role applied to all logstash servers"
 
 default_attributes(
-  :elasticsearch => {
-    :cluster => {
-      :name => "logstash"
-    },
-    :version => "6.x"
-  },
   :kibana => {
     :sites => {
       :logstash => {
index 6639332e32f1d15736ec153527bd85c35f0c5594..a3502c6df329d9f0852fb6a2ce09b6514aab665e 100644 (file)
@@ -7,6 +7,9 @@ default_attributes(
       :root => "ceasar"
     }
   },
+  :hardware => {
+    :shm_size => "20g"
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -28,16 +31,25 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "12500 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "16384 MB",
+    :cache_dir => [
+      "rock /store.new-san/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store.new-san/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store.new-san/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store.new-san/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
+  },
+  :nginx => {
+    :cache => {
+      :proxy => {
+        :directory => "/store.new-san/nginx-cache/proxy-cache",
+        :max_size => "65536M"
+      }
+    }
   },
   :tilecache => {
-    :tile_parent => "hsinchu.render.openstreetmap.org",
-    :tile_siblings => [
-      "balerion.openstreetmap.org",
-      "waima.openstreetmap.org",
-      "tuatara.openstreetmap.org"
-    ]
+    :tile_parent => "hsinchu.render.openstreetmap.org"
   }
 )
 
diff --git a/roles/lu.rb b/roles/lu.rb
new file mode 100644 (file)
index 0000000..dd381e5
--- /dev/null
@@ -0,0 +1,11 @@
+name "lu"
+description "Role applied to all servers located in Luxembourg"
+
+override_attributes(
+  :country => "lu",
+  :timezone => "Europe/Luxembourg"
+)
+
+run_list(
+  "role[base]"
+)
index a5aff59e0b33853778abbada6fe3fce94d3ef8d7..b44835628a604878f925deac9b6b82ec066cd6a4 100644 (file)
@@ -4,19 +4,12 @@ description "Role applied to all servers at LyonIX"
 default_attributes(
   :hosted_by => "LyonIX",
   :location => "Lyon, France",
-  :networking => {
-    :nameservers => ["77.95.64.205", "77.95.64.206", "8.8.8.8", "8.8.4.4"],
-    :roles => {
-      :external => {
-        :zone => "ly"
-      }
-    }
-  },
   :snmpd => {
-    :clients => ["77.95.64.0/24", "77.95.70.0/24"],
+    :clients => ["77.95.64.0/21"],
+    :clients6 => ["2a03:9180::/32", "2001:7f8:47::/48"],
     :community => "lyonix",
     :location => "LYON",
-    :contact => "noc@lyonix.net"
+    :contact => "sysadm@rezopole.net"
   }
 )
 
index 22f34ea5273cf744611118e341601c47ad33ec82..09c2aaff7e588471b218f4677f44aab6c7216947 100644 (file)
@@ -9,18 +9,13 @@ default_attributes(
     }
   },
   :hosted_by => "Lysator",
-  :location => "Linköping, Sweden",
-  :networking => {
-    :nameservers => ["130.236.254.225", "2001:6b0:17:f0a0::e1", "130.236.254.4"],
-    :roles => {
-      :external => {
-        :zone => "osm"
-      }
-    }
-  }
+  :location => "Linköping, Sweden"
 )
 
 override_attributes(
+  :networking => {
+    :nameservers => ["130.236.254.225", "2001:6b0:17:f0a0::e1", "130.236.254.4"]
+  },
   :ntp => {
     :servers => ["0.se.pool.ntp.org", "1.se.pool.ntp.org", "europe.pool.ntp.org"]
   }
index 483260bb0df9981095e2e5efddb555c6a72c1094..77b3bf3f40a860cc90a8bf932f420aafecc9bb3c 100644 (file)
@@ -18,8 +18,15 @@ default_attributes(
     :daemon_smtp_ports => [25, 26],
     :certificate_names => [
       "mail.openstreetmap.org",
-      "a.mx.openstreetmap.org"
+      "a.mx.openstreetmap.org",
+      "a.mx.osm.org",
+      "a.mx.openstreetmap.com",
+      "a.mx.openstreetmap.io",
+      "a.mx.openstreetmap.pro",
+      "a.mx.openstreetmaps.org",
+      "a.mx.osm.io"
     ],
+    :queue_run_max => 5,
     :smarthost_name => "mail.openstreetmap.org",
     :smarthost_via => false,
     :dns_blacklists => ["zen.spamhaus.org"],
@@ -34,17 +41,16 @@ default_attributes(
         :domains => ["otrs.openstreetmap.org"],
         :host => "ridley.ucl.openstreetmap.org"
       },
-      :tickets => {
-        :comment => "tickets.openstreetmap.org",
-        :domains => ["tickets.openstreetmap.org"],
-        :host => "ridley.ucl.openstreetmap.org"
-      },
       :join => {
         :comment => "join.osmfoundation.org",
         :domains => ["join.osmfoundation.org"],
         :host => "ridley.ucl.openstreetmap.org"
       }
     },
+    :dkim_selectors => {
+      "openstreetmap.org" => "20200301",
+      "osmfoundation.org" => "20201112"
+    },
     :aliases => {
       "abuse" => "root",
       "postmaster" => "root",
@@ -53,6 +59,7 @@ default_attributes(
       "rails" => "root",
       "trac" => "root",
       "munin" => "root",
+      "prometheus" => "root",
       "www-data" => "root",
       "osmbackup" => "root",
       "noreply" => "/dev/null",
@@ -68,7 +75,8 @@ default_attributes(
       "support" => "support@otrs.openstreetmap.org",
       "memorial" => "communication@osmfoundation.org",
       "legal" => "legal@osmfoundation.org",
-      "dmca" => "dmca@osmfoundation.org"
+      "dmca" => "dmca@osmfoundation.org",
+      "program-sotm" => "sotm-program@otrs.openstreetmap.org"
     },
     :private_aliases => "mail"
   },
@@ -86,5 +94,6 @@ default_attributes(
 
 run_list(
   "recipe[clamav]",
+  "recipe[exim]",
   "recipe[spamassassin]"
 )
diff --git a/roles/meraxes.rb b/roles/meraxes.rb
new file mode 100644 (file)
index 0000000..bd34c69
--- /dev/null
@@ -0,0 +1,46 @@
+name "meraxes"
+description "Master role applied to meraxes"
+
+default_attributes(
+  :hardware => {
+    :shm_size => "36g"
+  },
+  :networking => {
+    :interfaces => {
+      :external_ipv4 => {
+        :interface => "enp1s0f0",
+        :role => :external,
+        :family => :inet,
+        :address => "51.15.185.90",
+        :prefix => "24",
+        :gateway => "51.15.185.1"
+      },
+      :external_ipv6 => {
+        :interface => "enp1s0f0",
+        :role => :external,
+        :family => :inet6,
+        :address => "2001:bc8:2d57:100:aa1e:84ff:fe72:e660",
+        :prefix => "48",
+        :gateway => "2001:bc8:2::2:258:1"
+      }
+    }
+  },
+  :squid => {
+    :version => 4,
+    :cache_mem => "32768 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
+  },
+  :tilecache => {
+    :tile_parent => "france.render.openstreetmap.org"
+  }
+)
+
+run_list(
+  "role[scaleway]",
+  "role[tilecache]"
+)
index d84cf531945097c7ae8b5fbf91b07b8c8963228e..d353814abdf847902350cc2b1837c3b57920e939 100644 (file)
@@ -23,12 +23,6 @@ default_attributes(
           :connection_limit => "-"
         }
       ]
-    },
-    :nameservers => ["130.117.11.11", "2a0b:cbc0:42::42"],
-    :roles => {
-      :external => {
-        :zone => "osm"
-      }
     }
   }
 )
index 23e80f320a7df0a154eb7e635c78533310c07135..5ff6a358874a83775861af755026194668cecb28 100644 (file)
@@ -2,41 +2,45 @@ name "naga"
 description "Master role applied to naga"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "14g"
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
         :interface => "ens18",
         :role => :external,
         :family => :inet,
-        :address => "185.216.27.232",
-        :prefix => "24",
-        :gateway => "185.216.27.253"
+        :address => "45.13.104.40",
+        :prefix => "32",
+        :gateway => "10.0.4.1"
       },
       :external_ipv6 => {
         :interface => "ens18",
         :role => :external,
         :family => :inet6,
-        :address => "2a07:abc4:5::27:244",
-        :prefix => "24",
-        :gateway => "fe80::20c:29ff:fe4d:941b"
+        :address => "2a0b:cbc0:1101:1::41",
+        :prefix => "64",
+        :gateway => "2a0b:cbc0:1101:1::1"
       }
     }
   },
   :squid => {
-    :cache_mem => "12500 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "10240 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
   },
   :tilecache => {
-    :tile_parent => "france.render.openstreetmap.org",
-    :tile_siblings => [
-      "noomoahk.openstreetmap.org",
-      "norbert.openstreetmap.org",
-      "ladon.openstreetmap.org"
-    ]
+    :tile_parent => "france.render.openstreetmap.org"
   }
 )
 
 run_list(
-  "role[proxgroup]",
+  "role[milkywan]",
   "role[tilecache]"
 )
index bb9181fff5d6a0bc91514dfcb4d7e76a2cf4d2b6..1c434df2aac0f53d447b07be04fc96148a795bbc 100644 (file)
@@ -11,18 +11,16 @@ default_attributes(
   :hosted_by => "NCHC",
   :location => "Hsinchu, Taiwan",
   :networking => {
-    :nameservers => ["140.110.16.1", "140.110.4.1"],
-    :roles => {
-      :external => {
-        :zone => "nc"
-      }
-    }
+    :wireguard => { :keepalive => 180 }
   }
 )
 
 override_attributes(
+  :networking => {
+    :nameservers => ["140.110.16.1", "140.110.4.1"]
+  },
   :ntp => {
-    :servers => ["0.tw.pool.ntp.org", "1.tw.pool.ntp.org", "europe.pool.ntp.org"]
+    :servers => ["0.tw.pool.ntp.org", "1.tw.pool.ntp.org", "asia.pool.ntp.org"]
   }
 )
 
diff --git a/roles/neak.rb b/roles/neak.rb
new file mode 100644 (file)
index 0000000..b54155b
--- /dev/null
@@ -0,0 +1,38 @@
+name "neak"
+description "Master role applied to neak"
+
+default_attributes(
+  :hardware => {
+    :shm_size => "14g"
+  },
+  :networking => {
+    :interfaces => {
+      :external_ipv4 => {
+        :interface => "ens18",
+        :role => :external,
+        :family => :inet,
+        :address => "89.234.177.142",
+        :prefix => "26",
+        :gateway => "89.234.177.129"
+      }
+    }
+  },
+  :squid => {
+    :version => 4,
+    :cache_mem => "10240 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
+  },
+  :tilecache => {
+    :tile_parent => "france.render.openstreetmap.org"
+  }
+)
+
+run_list(
+  "role[faimaison]",
+  "role[tilecache]"
+)
index ea065055619f5c7cc5d49074c6e608ae51484133..09cfdb11804b740ecc7363f2c6a0170ddb1eb616 100644 (file)
@@ -5,41 +5,63 @@ default_attributes(
   :networking => {
     :interfaces => {
       :external_ipv4 => {
-        :interface => "ens18",
+        :interface => "bond0",
+        :mtu => 9000,
         :role => :external,
         :family => :inet,
-        :address => "80.67.167.77",
-        :prefix => "32",
-        :gateway => "10.0.6.1"
+        :address => "45.85.134.91",
+        :prefix => "31",
+        :gateway => "45.85.134.90",
+        :bond => {
+          :slaves => %w[eno1 eno2],
+          :mode => "802.3ad",
+          :lacprate => "fast"
+        }
       },
       :external_ipv6 => {
-        :interface => "ens18",
+        :interface => "bond0",
         :role => :external,
         :family => :inet6,
-        :address => "2a0b:cbc0:110d:1::1c",
+        :address => "2a05:46c0:100:1004:ffff:ffff:ffff:ffff",
         :prefix => "64",
-        :gateway => "2a0b:cbc0:110d:1::1"
+        :gateway => "2a05:46c0:100:1004::"
       }
     }
   },
-  :squid => {
-    :cache_mem => "7500 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+  :postgresql => {
+    :settings => {
+      :defaults => {
+        :shared_buffers => "8GB",
+        :maintenance_work_mem => "7144MB",
+        :effective_cache_size => "16GB"
+      }
+    }
   },
-  :tilecache => {
-    :tile_parent => "france.render.openstreetmap.org",
-    :tile_siblings => [
-      # "necrosan.openstreetmap.org",
-      "nepomuk.openstreetmap.org",
-      "noomoahk.openstreetmap.org",
-      "norbert.openstreetmap.org",
-      "ladon.openstreetmap.org",
-      "gorynych.openstreetmap.org"
-    ]
+  :sysctl => {
+    :postgres => {
+      :comment => "Increase shared memory for postgres",
+      :parameters => {
+        "kernel.shmmax" => 9 * 1024 * 1024 * 1024,
+        "kernel.shmall" => 9 * 1024 * 1024 * 1024 / 4096
+      }
+    }
+  },
+  :tile => {
+    :database => {
+      :cluster => "12/main",
+      :postgis => "3"
+    },
+    :styles => {
+      :default => {
+        :tile_directories => [
+          { :name => "/store/tiles/default", :min_zoom => 0, :max_zoom => 19 }
+        ]
+      }
+    }
   }
 )
 
 run_list(
-  "role[milkywan]",
-  "role[tilecache]"
+  "role[appliwave]",
+  "role[tile]"
 )
index 17e048d9acbe93b6112ff08b44f9d0fea94dcbc4..12277629d091abbc4b77c474d39785fef5916c64 100644 (file)
@@ -2,6 +2,9 @@ name "nepomuk"
 description "Master role applied to nepomuk"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "14g"
+  },
   :networking => {
     :firewall => {
       :inet => [
@@ -46,8 +49,14 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "7500 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "10240 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
   },
   :sysfs => {
     :hdd_tune => {
@@ -58,15 +67,7 @@ default_attributes(
     }
   },
   :tilecache => {
-    :tile_parent => "france.render.openstreetmap.org",
-    :tile_siblings => [
-      # "necrosan.openstreetmap.org", # IO Overloaded
-      # "nepomuk.openstreetmap.org",
-      "noomoahk.openstreetmap.org",
-      "norbert.openstreetmap.org",
-      "ladon.openstreetmap.org",
-      "gorynych.openstreetmap.org"
-    ]
+    :tile_parent => "france.render.openstreetmap.org"
   }
 )
 
index 41f1908325e9815c4735b57f9a21ac342b4f0f69..bbccac112d7d9ea9a1147699b490bd932e426620 100644 (file)
@@ -4,23 +4,15 @@ description "Role applied to all servers at NetAlerts"
 default_attributes(
   :hosted_by => "NetAlerts",
   :location => "Montréal, Canada",
-  :timezone => "America/Montreal",
-  :networking => {
-    :nameservers => [
-      "209.172.41.202",
-      "209.172.41.200"
-    ],
-    :roles => {
-      :external => {
-        :zone => "na"
-      }
-    }
-  }
+  :timezone => "America/Montreal"
 )
 
 override_attributes(
+  :networking => {
+    :nameservers => ["209.172.41.202", "209.172.41.200"]
+  },
   :ntp => {
-    :servers => ["0.ca.pool.ntp.org", "1.ca.pool.ntp.org", "america.pool.ntp.org"]
+    :servers => ["0.ca.pool.ntp.org", "1.ca.pool.ntp.org", "north-america.pool.ntp.org"]
   }
 )
 
index e173757659934d92465ffda7c7181eabe9b4caf1..451950fdba167ebfc1b4df526abb9c1ac4828e8d 100644 (file)
@@ -2,6 +2,9 @@ name "nidhogg"
 description "Master role applied to nidhogg"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "14g"
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -23,17 +26,17 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "7500 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "10240 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
   },
   :tilecache => {
-    :tile_parent => "sweden.render.openstreetmap.org",
-    :tile_siblings => [
-      "fafnir.openstreetmap.org",
-      "ridgeback.openstreetmap.org",
-      "rimfaxe.openstreetmap.org",
-      "trogdor.openstreetmap.org"
-    ]
+    :tile_parent => "sweden.render.openstreetmap.org"
   }
 )
 
index 9564e11831d4a3e7ed6689ff490e00c1ae9afb3a..cb68665420458e7b18f36ca06547f75d55b84268 100644 (file)
@@ -14,23 +14,22 @@ default_attributes(
   },
   :apache => {
     :mpm => "event",
-    :timeout => 60,
+    :timeout => 30,
     :keepalive => false,
     :reqtimeout => true,
     :event => {
-      :server_limit => 32,
-      :max_request_workers => 1600,
+      :server_limit => 100,
+      :max_request_workers => 2400,
       :threads_per_child => 50,
       :min_spare_threads => 125,
-      :max_spare_threads => 925
+      :max_spare_threads => 925,
+      :async_request_worker_factor => 4,
+      :listen_cores_buckets_ratio => 6
     }
   },
-  :apt => {
-    :sources => ["postgresql"]
-  },
   :networking => {
     :firewall => {
-      :http_rate_limit => "s:7/sec:15"
+      :http_rate_limit => "s:2/sec:15"
     }
   },
   :postgresql => {
@@ -76,7 +75,7 @@ default_attributes(
     :network_conntrack_max => {
       :comment => "Increase max number of connections tracked",
       :parameters => {
-        "net.netfilter.nf_conntrack_max" => "131072"
+        "net.netfilter.nf_conntrack_max" => "196608"
       }
     }
   }
diff --git a/roles/noomoahk.rb b/roles/noomoahk.rb
deleted file mode 100644 (file)
index eeb4b00..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-name "noomoahk"
-description "Master role applied to noomoahk"
-
-default_attributes(
-  :networking => {
-    :interfaces => {
-      :external_ipv4 => {
-        :interface => "ens3",
-        :role => :external,
-        :family => :inet,
-        :address => "91.224.148.166",
-        :prefix => "32",
-        :gateway => "89.234.156.230"
-      },
-      :external_ipv6 => {
-        :interface => "ens3",
-        :role => :external,
-        :family => :inet6,
-        :address => "2a03:7220:8080:a600::1",
-        :prefix => "56",
-        :gateway => "fe80::1"
-      }
-    }
-  },
-  :squid => {
-    :cache_mem => "3100 MB",
-    :cache_dir => "coss /store/squid/coss-01 80000 block-size=8192 max-size=262144 membufs=80"
-  },
-  :tilecache => {
-    :tile_parent => "france.render.openstreetmap.org",
-    :tile_siblings => [
-      # "necrosan.openstreetmap.org", # IO Overloaded
-      "nepomuk.openstreetmap.org",
-      # "noomoahk.openstreetmap.org",
-      "norbert.openstreetmap.org",
-      "ladon.openstreetmap.org",
-      "gorynych.openstreetmap.org"
-    ]
-  }
-)
-
-run_list(
-  "role[tetaneutral]",
-  "role[tilecache]"
-)
index 8476393d68bf5518a2b2aeb604d78bd58c5a518c..15433754edc46cbb9314b761ce7d3cdadf703301 100644 (file)
@@ -2,6 +2,9 @@ name "norbert"
 description "Master role applied to norbert"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "12g"
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -23,15 +26,25 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "7500 MB",
-    :cache_dir => "coss /store/squid/coss-01 80000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "10240 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
+  },
+  :nginx => {
+    :cache => {
+      :proxy => {
+        :keys_zone => "proxy_cache_zone:64M",
+        :max_size => "2048M"
+      }
+    }
   },
   :tilecache => {
-    :tile_parent => "france.render.openstreetmap.org",
-    :tile_siblings => [
-      "noomoahk.openstreetmap.org",
-      "ladon.openstreetmap.org"
-    ]
+    :tile_parent => "france.render.openstreetmap.org"
   }
 )
 
index b6c64a1b1a8d8a946392913a3a6aaf297a8d74ac..238e403ae90f54ffd6174a20772a5a7b236b2f25 100644 (file)
@@ -2,9 +2,6 @@ name "odin"
 description "Master role applied to odin"
 
 default_attributes(
-  :apt => {
-    :sources => ["postgresql"]
-  },
   :networking => {
     :interfaces => {
       :internal_ipv4 => {
@@ -31,7 +28,6 @@ default_attributes(
     }
   },
   :postgresql => {
-    :versions => ["10"],
     :settings => {
       :defaults => {
         :shared_buffers => "8GB",
@@ -51,10 +47,9 @@ default_attributes(
   },
   :tile => {
     :database => {
-      :cluster => "10/main",
-      :postgis => "2.4"
+      :cluster => "12/main",
+      :postgis => "3"
     },
-    :node_file => "/store/database/nodes",
     :styles => {
       :default => {
         :tile_directories => [
index e8caaf82e9a17f6351932df07cf90409794c2771..860ab8c3d835f494934614b6d24e5c7fb5901df4 100644 (file)
@@ -3,17 +3,6 @@ description "Master role applied to orm"
 
 default_attributes(
   :devices => {
-    :ssd_samsung => {
-      :comment => "Tune scheduler for SSD",
-      :type => "block",
-      :bus => "ata",
-      :serial => "Samsung_SSD_840_PRO_Series_*",
-      :attrs => {
-        "queue/scheduler" => "noop",
-        "queue/nr_requests" => "256",
-        "queue/read_ahead_kb" => "2048"
-      }
-    },
     :arecavoltune => {
       :comment => "Tune scheduler for Areca",
       :type => "block",
@@ -62,12 +51,6 @@ default_attributes(
   }
 )
 
-override_attributes(
-  :networking => {
-    :nameservers => ["8.8.8.8", "8.8.4.4"]
-  }
-)
-
 run_list(
   "role[equinix]",
   "role[tyan-s7010]"
index da7036fe05214fc3b7f592ffe7953a446b38664b..45a4cf04c1bca0aa8f0eb7e99908252faf8012c9 100644 (file)
@@ -2,11 +2,6 @@ name "osqa"
 description "Role applied to all OSQA servers"
 
 default_attributes(
-  :accounts => {
-    :users => {
-      :osqa => { :status => :role }
-    }
-  },
   :osqa => {
     :sites => [
       { :name => "help.openstreetmap.org",
index f80b1177a2fae2f824922a527ee91f17f08e3ac0..899176dcbca7fac1579fc1a9f112d0a3532941fe 100644 (file)
@@ -11,10 +11,8 @@ default_attributes(
   :location => "Corvallis, Oregon",
   :timezone => "PST8PDT",
   :networking => {
-    :nameservers => ["8.8.8.8", "8.8.4.4"],
     :roles => {
       :external => {
-        :zone => "ool",
         :inet => {
           :prefix => "28",
           :gateway => "140.211.167.97"
index c895b122a6fa98b3780bb3a778684cb3022aba35..159af75a5a61678aff5393cb58eb21ede70d5205 100644 (file)
@@ -2,16 +2,6 @@ name "otrs"
 description "Role applied to all OTRS servers"
 
 default_attributes(
-  :accounts => {
-    :users => {
-      :otrs => { :status => :role }
-    },
-    :groups => {
-      :"www-data" => {
-        :members => [:otrs]
-      }
-    }
-  },
   :exim => {
     :local_domains => ["otrs.openstreetmap.org"],
     :routes => {
@@ -42,6 +32,15 @@ default_attributes(
         :group => "www-data",
         :home_directory => "/opt/otrs"
       },
+      :otrs_membership_osmf_talk_owner => {
+        :comment => "osmf-talk-owner@otrs.openstreetmap.org",
+        :domains => ["otrs.openstreetmap.org"],
+        :local_parts => ["osmf-talk-owner"],
+        :command => "/opt/otrs/bin/otrs.Console.pl Maint::PostMaster::Read --target-queue 'Membership Working Group::osmf-talk'",
+        :user => "otrs",
+        :group => "www-data",
+        :home_directory => "/opt/otrs"
+      },
       :otrs_legal => {
         :comment => "legal@otrs.openstreetmap.org",
         :domains => ["otrs.openstreetmap.org"],
@@ -78,6 +77,15 @@ default_attributes(
         :group => "www-data",
         :home_directory => "/opt/otrs"
       },
+      :otrs_sotm_program => {
+        :comment => "sotm-program@otrs.openstreetmap.org",
+        :domains => ["otrs.openstreetmap.org"],
+        :local_parts => ["sotm-program"],
+        :command => "/opt/otrs/bin/otrs.Console.pl Maint::PostMaster::Read --target-queue 'State of the Map:Program'",
+        :user => "otrs",
+        :group => "www-data",
+        :home_directory => "/opt/otrs"
+      },
       :otrs_support => {
         :comment => "support@otrs.openstreetmap.org",
         :domains => ["otrs.openstreetmap.org"],
@@ -91,14 +99,7 @@ default_attributes(
   },
   :otrs => {
     :site => "otrs.openstreetmap.org",
-    :site_aliases => ["otrs.osm.org"],
-    :database_cluster => "10/main",
-    :database_name => "otrs",
-    :database_user => "otrs",
-    :database_password => "otrs"
-  },
-  :postgresql => {
-    :versions => ["10"]
+    :site_aliases => ["otrs.osm.org"]
   }
 )
 
index 506be9c9a14ef5a8c2c211e6de9eb7317738cf9d..f8391a2aa941ae1d535850de69e3743c2d13f2e0 100644 (file)
@@ -3,20 +3,13 @@ description "Role applied to all servers at OVH"
 
 default_attributes(
   :hosted_by => "OVH",
-  :location => "Roubaix, France",
-  :networking => {
-    :nameservers => [
-      "213.186.33.99"
-    ],
-    :roles => {
-      :external => {
-        :zone => "ovh"
-      }
-    }
-  }
+  :location => "Roubaix, France"
 )
 
 override_attributes(
+  :networking => {
+    :nameservers => ["213.186.33.99"]
+  },
   :ntp => {
     :servers => ["0.fr.pool.ntp.org", "1.fr.pool.ntp.org", "europe.pool.ntp.org"]
   }
index b84b86c96ca6d91f046a5e84b423b2f604b8d16a..516546968c35a112d77e8ae2ef41a2206efeb0bf 100644 (file)
@@ -12,18 +12,13 @@ default_attributes(
   :location => "Pau, France",
   :munin => {
     :allow => ["10.64.1.11"]
-  },
-  :networking => {
-    :nameservers => ["10.64.1.42", "194.167.156.13", "10.64.1.3"],
-    :roles => {
-      :external => {
-        :zone => "pa"
-      }
-    }
   }
 )
 
 override_attributes(
+  :networking => {
+    :nameservers => ["10.64.1.42", "194.167.156.13", "10.64.1.3"]
+  },
   :ntp => {
     :servers => ["cannelle.paulla.asso.fr"]
   }
index 886784be0a3806f451f1bdcaf82adea1430f23c6..7f161753b54a5a911c8aef718b3fb20225282ce5 100644 (file)
@@ -3,10 +3,13 @@ description "Role applied to all Piwik servers"
 
 default_attributes(
   :apache => {
-    :mpm => "prefork",
-    :prefork => {
-      :server_limit => 450,
-      :max_request_workers => 450
+    :mpm => "event",
+    :event => {
+      :server_limit => 18,
+      :max_request_workers => 450,
+      :min_spare_threads => 50,
+      :max_spare_threads => 150,
+      :listen_cores_buckets_ratio => 4
     }
   },
   :mysql => {
diff --git a/roles/pl.rb b/roles/pl.rb
new file mode 100644 (file)
index 0000000..ad8a61d
--- /dev/null
@@ -0,0 +1,11 @@
+name "pl"
+description "Role applied to all servers located in Poland"
+
+override_attributes(
+  :country => "pl",
+  :timezone => "Europe/Warsaw"
+)
+
+run_list(
+  "role[base]"
+)
index 6c765845bb7f4893bfba6f900383638c76e2cfbf..7afcd2662d75c12f612e04e4b6e64341df357b6b 100644 (file)
@@ -2,15 +2,6 @@ name "planet"
 description "Role applied to all planet servers"
 
 default_attributes(
-  :accounts => {
-    :users => {
-      :bretth => { :status => :user },
-      :planet => {
-        :status => :administrator,
-        :members => [:bretth]
-      }
-    }
-  },
   :rsyncd => {
     :modules => {
       :planet => {
@@ -37,14 +28,15 @@ default_attributes(
     }
   },
   :apache => {
-    :mpm => "worker",
+    :mpm => "event",
     :keepalive => true,
-    :worker => {
+    :event => {
       :server_limit => 20,
       :max_request_workers => 1000,
       :threads_per_child => 50,
       :min_spare_threads => 75,
-      :max_spare_threads => 525
+      :max_spare_threads => 525,
+      :listen_cores_buckets_ratio => 4
     }
   }
 )
diff --git a/roles/prgmr.rb b/roles/prgmr.rb
deleted file mode 100644 (file)
index e6816eb..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-name "prgmr"
-description "Role applied to all servers at prgmr.com"
-
-default_attributes(
-  :hosted_by => "prgmr.com",
-  :location => "San Francisco, California",
-  :timezone => "PST8PDT",
-  :networking => {
-    :nameservers => ["8.8.4.4", "65.19.174.2", "65.19.175.2"],
-    :roles => {
-      :external => {
-        :zone => "pr"
-      }
-    }
-  }
-)
-
-override_attributes(
-  :ntp => {
-    :servers => ["0.us.pool.ntp.org", "1.us.pool.ntp.org", "2.us.pool.ntp.org"]
-  }
-)
-
-run_list(
-  "role[us]"
-)
diff --git a/roles/prometheus.rb b/roles/prometheus.rb
new file mode 100644 (file)
index 0000000..84a1766
--- /dev/null
@@ -0,0 +1,35 @@
+name "prometheus"
+description "Role applied to all prometheus servers"
+
+default_attributes(
+  :postgresql => {
+    :settings => {
+      :defaults => {
+        :max_connections => "500",
+        :shared_buffers => "48GB",
+        :work_mem => "8MB",
+        :maintenance_work_mem => "2GB",
+        :effective_io_concurrency => "200",
+        :max_worker_processes => "67",
+        :max_parallel_workers_per_gather => "28",
+        :max_parallel_workers => "56",
+        :wal_buffers => "16MB",
+        :max_wal_size => "32GB",
+        :min_wal_size => "4GB",
+        :checkpoint_completion_target => "0.9",
+        :random_page_cost => "1.1",
+        :effective_cache_size => "144GB",
+        :default_statistics_target => "500",
+        :log_autovacuum_min_duration => "0",
+        :autovacuum_max_workers => "10",
+        :autovacuum_naptime => "10",
+        :autovacuum_multixact_freeze_max_age => "200000000",
+        :max_locks_per_transaction => "512"
+      }
+    }
+  }
+)
+
+run_list(
+  "recipe[prometheus::server]"
+)
diff --git a/roles/proxgroup.rb b/roles/proxgroup.rb
deleted file mode 100644 (file)
index 31b7dc5..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-name "proxgroup"
-description "Role applied to all servers at ProxGroup"
-
-default_attributes(
-  :hosted_by => "ProxGroup",
-  :location => "Paris, France",
-  :networking => {
-    :nameservers => ["8.8.8.8", "8.8.4.4"],
-    :roles => {
-      :external => {
-        :zone => "osm"
-      }
-    }
-  }
-)
-
-override_attributes(
-  :ntp => {
-    :servers => ["0.fr.pool.ntp.org", "1.fr.pool.ntp.org", "europe.pool.ntp.org"]
-  }
-)
-
-run_list(
-  "role[fr]"
-)
index e431a66455a9efb8ce98f4fb5c65ed6c01a31665..05393514c155b5ecca84cc774c7a620ab8b9ed26 100644 (file)
@@ -4,14 +4,20 @@ description "Master role applied to pummelzacken"
 default_attributes(
   :networking => {
     :interfaces => {
+      :bond => {
+        :interface => "bond0",
+        :bond => {
+          :slaves => %w[eno1 enp5s0f0]
+        }
+      },
       :internal_ipv4 => {
-        :interface => "em1.2801",
+        :interface => "bond0.2801",
         :role => :internal,
         :family => :inet,
         :address => "10.0.0.20"
       },
       :external_ipv4 => {
-        :interface => "em1.2800",
+        :interface => "bond0.2800",
         :role => :external,
         :family => :inet,
         :address => "193.60.236.18"
@@ -19,7 +25,7 @@ default_attributes(
     }
   },
   :postgresql => {
-    :versions => ["10"],
+    :versions => ["13"],
     :settings => {
       :defaults => {
         :listen_addresses => "10.0.0.20",
@@ -27,15 +33,22 @@ default_attributes(
         :maintenance_work_mem => "10GB",
         :random_page_cost => "1.5",
         :effective_cache_size => "60GB",
+        :effective_io_concurrency => "256",
         :fsync => "on"
       }
     }
   },
+  :apache => {
+    :event => {
+      :max_request_workers => 3000,
+      :threads_per_child => 70
+    }
+  },
   :nominatim => {
     :state => "standalone",
     :dbadmins => %w[lonvia tomh],
-    :dbcluster => "10/main",
-    :postgis => "2.4",
+    :dbcluster => "13/main",
+    :postgis => "3",
     :enable_backup => true,
     :flatnode_file => "/ssd/nominatim/nodes.store",
     :tablespaces => {
@@ -49,11 +62,6 @@ default_attributes(
       "isearch" => "/ssd/tablespaces/isearch",
       "daux" => "/data/tablespaces/daux",
       "iaux" => "/data/tablespaces/iaux"
-    },
-    :fpm_pools => {
-      :www => {
-        :max_children => "40"
-      }
     }
   }
 )
index b3bee0f770bfa0d64cd31ad42ad6e182ca95a533..7d03d02e3ae3b61539abfa3499db5b7c9b3ca672 100644 (file)
@@ -2,14 +2,21 @@ name "pyrene"
 description "Master role applied to pyrene"
 
 default_attributes(
-  :apt => {
-    :sources => ["postgresql"]
-  },
   :munin => {
     :plugins => {
       :hpasmcli2_temp => {
         :temp15 => { :warning => "59.5", :critical => "70" },
         :temp17 => { :warning => "59.5", :critical => "70" }
+      },
+      :hpasmcli2_fans => {
+        :fan1 => { :warning => "95", :critical => "100" },
+        :fan2 => { :warning => "95", :critical => "100" },
+        :fan3 => { :warning => "95", :critical => "100" },
+        :fan4 => { :warning => "95", :critical => "100" },
+        :fan5 => { :warning => "95", :critical => "100" },
+        :fan6 => { :warning => "95", :critical => "100" },
+        :fan7 => { :warning => "95", :critical => "100" },
+        :fan8 => { :warning => "95", :critical => "100" }
       }
     }
   },
@@ -30,7 +37,6 @@ default_attributes(
     }
   },
   :postgresql => {
-    :versions => ["10"],
     :settings => {
       :defaults => {
         :shared_buffers => "8GB",
@@ -50,10 +56,9 @@ default_attributes(
   },
   :tile => {
     :database => {
-      :cluster => "10/main",
-      :postgis => "2.4"
+      :cluster => "12/main",
+      :postgis => "3"
     },
-    :node_file => "/store/database/nodes",
     :styles => {
       :default => {
         :tile_directories => [
index b29de0fa1d2efc000daae7a46c22d5962fb803d6..00fce56cf4345c2d21baaadc745700ccc9287abb 100644 (file)
@@ -7,27 +7,29 @@ default_attributes(
       :mmiler => { :status => :administrator }
     }
   },
-  :apt => {
-    :sources => ["postgresql"]
-  },
-  :devices => {
-    :ssd_samsung => {
-      :comment => "Tune scheduler for SSD",
-      :type => "block",
-      :bus => "ata",
-      :serial => "Samsung_SSD_860_PRO_*",
-      :attrs => {
-        "queue/scheduler" => "noop",
-        "queue/nr_requests" => "256",
-        "queue/read_ahead_kb" => "2048"
+  :location => "Zagreb, Croatia",
+  :munin => {
+    :plugins => {
+      :sensors_temp => {
+        :temp1 => { :warning => "85.0" },
+        :temp2 => { :warning => "85.0" },
+        :temp3 => { :warning => "85.0" },
+        :temp4 => { :warning => "85.0" },
+        :temp5 => { :warning => "85.0" },
+        :temp6 => { :warning => "85.0" },
+        :temp8 => { :warning => "85.0" },
+        :temp9 => { :warning => "85.0" },
+        :temp10 => { :warning => "85.0" },
+        :temp11 => { :warning => "85.0" },
+        :temp12 => { :warning => "85.0" },
+        :temp13 => { :warning => "85.0" }
       }
     }
   },
-  :location => "Zagreb, Croatia",
   :networking => {
     :interfaces => {
       :external_ipv4 => {
-        :interface => "enp1s0f0",
+        :interface => "eno1",
         :role => :external,
         :family => :inet,
         :address => "10.5.0.77",
@@ -35,14 +37,9 @@ default_attributes(
         :gateway => "10.5.0.1",
         :public_address => "161.53.248.77"
       }
-    },
-    :nameservers => [
-      "10.5.0.7",
-      "8.8.8.8"
-    ]
+    }
   },
   :postgresql => {
-    :versions => ["10"],
     :settings => {
       :defaults => {
         :shared_buffers => "8GB",
@@ -62,10 +59,9 @@ default_attributes(
   },
   :tile => {
     :database => {
-      :cluster => "10/main",
-      :postgis => "2.4"
+      :cluster => "12/main",
+      :postgis => "3"
     },
-    :node_file => "/store/database/nodes",
     :styles => {
       :default => {
         :tile_directories => [
index 5fa68580d9ef4d0533a8eb9eea8f6570797cff2f..9593ac4e06e8083f455b68849bc65d0b1f525d0d 100644 (file)
@@ -2,6 +2,12 @@ name "ridgeback"
 description "Master role applied to ridgeback"
 
 default_attributes(
+  :hardware => {
+    :ipmi => {
+      :excluded_sensors => [19, 20, 21, 22]
+    },
+    :shm_size => "10g"
+  },
   :munin => {
     :plugins => {
       :ipmi_fans => {
@@ -46,18 +52,17 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "5500 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "8192 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
   },
   :tilecache => {
-    :tile_parent => "oslo.render.openstreetmap.org",
-    :tile_siblings => [
-      "trogdor.openstreetmap.org",
-      "katie.openstreetmap.org",
-      "konqi.openstreetmap.org",
-      "gorynych.openstreetmap.org",
-      "simurgh.openstreetmap.org"
-    ]
+    :tile_parent => "oslo.render.openstreetmap.org"
   }
 )
 
index 591f31ae2fd00fb7936f73a35e5b84313c03cb93..d3ddde39d96ff9b6680ff11d6539ff07f4be38ea 100644 (file)
@@ -2,6 +2,16 @@ name "ridley"
 description "Master role applied to ridley"
 
 default_attributes(
+  :apache => {
+    :mpm => "event",
+    :event => {
+      :min_spare_threads => 50,
+      :max_spare_threads => 150,
+      :max_connections_per_child => 10000,
+      :async_request_worker_factor => 4,
+      :listen_cores_buckets_ratio => 4
+    }
+  },
   :bind => {
     :clients => "ucl"
   },
@@ -24,44 +34,6 @@ default_attributes(
         :address => "10.0.0.3"
       }
     }
-  },
-  :openvpn => {
-    :address => "10.0.16.1",
-    :tunnels => {
-      :ic2ucl => {
-        :port => "1194",
-        :mode => "client",
-        :peer => {
-          :host => "ironbelly.openstreetmap.org",
-          :port => "1194"
-        }
-      },
-      :shenron2ucl => {
-        :port => "1195",
-        :mode => "client",
-        :peer => {
-          :host => "shenron.openstreetmap.org",
-          :port => "1194"
-        }
-      },
-      :ucl2bm => {
-        :port => "1196",
-        :mode => "client",
-        :peer => {
-          :host => "grisu.openstreetmap.org",
-          :port => "1196"
-        }
-      },
-      :firefishy => {
-        :port => "1197",
-        :mode => "client",
-        :peer => {
-          :host => "home.firefishy.com",
-          :port => "1194",
-          :address => "10.0.16.201"
-        }
-      }
-    }
   }
 )
 
@@ -77,6 +49,5 @@ run_list(
   "role[donate]",
   "recipe[hot]",
   "recipe[dmca]",
-  "recipe[dhcpd]",
-  "recipe[openvpn]"
+  "recipe[dhcpd]"
 )
diff --git a/roles/rimfaxe.rb b/roles/rimfaxe.rb
deleted file mode 100644 (file)
index 1b6b34c..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-name "rimfaxe"
-description "Master role applied to rimfaxe"
-
-default_attributes(
-  :networking => {
-    :interfaces => {
-      :external_ipv4 => {
-        :interface => "eth0",
-        :role => :external,
-        :family => :inet,
-        :address => "130.225.254.109",
-        :prefix => "27",
-        :gateway => "130.225.254.97"
-      },
-      :external_ipv6 => {
-        :interface => "eth0",
-        :role => :external,
-        :family => :inet6,
-        :address => "2001:878:346::109",
-        :prefix => "64",
-        :gateway => "2001:878:346::97"
-      }
-    }
-  },
-  :squid => {
-    :cache_mem => "7000 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
-  },
-  :tilecache => {
-    :tile_parent => "aalborg.render.openstreetmap.org",
-    :tile_siblings => [
-      "katie.openstreetmap.org",
-      "konqi.openstreetmap.org",
-      "ridgeback.openstreetmap.org",
-      "gorynych.openstreetmap.org"
-    ]
-  }
-)
-
-run_list(
-  "role[dotsrc]",
-  "role[tilecache]"
-)
diff --git a/roles/roundup.rb b/roles/roundup.rb
deleted file mode 100644 (file)
index ec099e6..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-name "roundup"
-description "Role applied to all roundup servers"
-
-run_list(
-  "recipe[roundup]"
-)
index ebfbc312613661b285a073aec42cd7cfa7ea7b36..7da9a071463627441a88edbd8c9b6171110de997 100644 (file)
@@ -2,9 +2,6 @@ name "saphira"
 description "Master role applied to saphira"
 
 default_attributes(
-  :hardware => {
-    :shm_size => "9g"
-  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -24,32 +21,10 @@ default_attributes(
         :gateway => "fe80::fcff:ffff:feff:ffff"
       }
     }
-  },
-  :squid => {
-    :version => 4,
-    :cache_mem => "6144 MB",
-    :cache_dir => [
-      "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
-      "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
-      "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
-      "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
-    ]
-  },
-  :tilecache => {
-    :tile_parent => "london.render.openstreetmap.org",
-    :tile_siblings => [
-      "toothless.openstreetmap.org",
-      "trogdor.openstreetmap.org",
-      "katie.openstreetmap.org",
-      "konqi.openstreetmap.org",
-      "ridgeback.openstreetmap.org",
-      "gorynych.openstreetmap.org"
-    ]
   }
 )
 
 run_list(
   "role[jump]",
-  "role[geodns]",
-  "role[tilecache]"
+  "role[geodns]"
 )
index 647aa57c5e7a0f963c092729d2b426a6f6267dcc..ab1bf393b259706a5a450e7336db8d71a1cb9cfb 100644 (file)
@@ -2,10 +2,17 @@ name "sarel"
 description "Master role applied to sarel"
 
 default_attributes(
+  :apache => {
+    :mpm => "event",
+    :event => {
+      :min_spare_threads => 50,
+      :max_spare_threads => 150,
+      :listen_cores_buckets_ratio => 4
+    }
+  },
   :git => {
     :private_user => "chefrepo",
-    :private_group => "chefrepo",
-    :private_nodes => "fqdn:*"
+    :private_group => "chefrepo"
   },
   :networking => {
     :interfaces => {
index ce318fcf388a1b9b82c92a176fdf8fd7314988db..6cd1424f73c25cc4f22a71bc32882ec91aee397b 100644 (file)
@@ -2,6 +2,9 @@ name "sarkany"
 description "Master role applied to sarkany"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "8g"
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -23,17 +26,24 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "5100 MB",
-    :cache_dir => "coss /store/squid/coss-01 80000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "6144 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
+  },
+  :nginx => {
+    :cache => {
+      :proxy => {
+        :max_size => "4096M"
+      }
+    }
   },
   :tilecache => {
-    :tile_parent => "budapest.render.openstreetmap.org",
-    :tile_siblings => [
-      "katie.openstreetmap.org",
-      "konqi.openstreetmap.org",
-      "ridgeback.openstreetmap.org",
-      "gorynych.openstreetmap.org"
-    ]
+    :tile_parent => "budapest.render.openstreetmap.org"
   }
 )
 
diff --git a/roles/scaleway.rb b/roles/scaleway.rb
new file mode 100644 (file)
index 0000000..26833e1
--- /dev/null
@@ -0,0 +1,20 @@
+name "scaleway"
+description "Role applied to all servers at Scaleway"
+
+default_attributes(
+  :hosted_by => "Scaleway",
+  :location => "Paris, France"
+)
+
+override_attributes(
+  :networking => {
+    :nameservers => ["62.210.16.6", "62.210.16.7"]
+  },
+  :ntp => {
+    :servers => ["0.fr.pool.ntp.org", "1.fr.pool.ntp.org", "europe.pool.ntp.org"]
+  }
+)
+
+run_list(
+  "role[fr]"
+)
index 07c2932e46230752ed72f621c3247b24b8eaf011..876fb6905f4d8c4016b3040f00c14eb0c75a034a 100644 (file)
@@ -2,9 +2,6 @@ name "scorch"
 description "Master role applied to scorch"
 
 default_attributes(
-  :apt => {
-    :sources => ["postgresql"]
-  },
   :devices => {
     :ssd_system => {
       :comment => "Tune scheduler for system disk",
@@ -44,7 +41,6 @@ default_attributes(
     }
   },
   :postgresql => {
-    :versions => ["10"],
     :settings => {
       :defaults => {
         :shared_buffers => "8GB",
@@ -64,10 +60,9 @@ default_attributes(
   },
   :tile => {
     :database => {
-      :cluster => "10/main",
-      :postgis => "2.4"
+      :cluster => "12/main",
+      :postgis => "3"
     },
-    :node_file => "/store/database/nodes",
     :styles => {
       :default => {
         :tile_directories => [
index c3db86355878f4cb3b0f1e17c460b59b6daa7007..9e94e5edd97d70853a52000695a58c053ff4f271 100644 (file)
@@ -10,24 +10,17 @@ default_attributes(
     }
   },
   :hardware => {
+    :hwmon => {
+      "platform_it87_552" => {
+        :ignore => %w[in6]
+      }
+    },
     :mcelog => {
       :enabled => false
     },
     :modules => [
       "it87"
     ]
-  },
-  :openvpn => {
-    :address => "10.0.16.3",
-    :tunnels => {
-      :shenron2ucl => {
-        :port => "1194",
-        :mode => "server",
-        :peer => {
-          :host => "ridley.openstreetmap.org"
-        }
-      }
-    }
   }
 )
 
@@ -51,7 +44,8 @@ override_attributes(
         :gateway => "fe80::1"
       }
     },
-    :nameservers => ["89.16.162.20", "2001:41c9:2:d6::20"]
+    :nameservers => ["1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001"],
+    :private_address => "10.0.16.100"
   }
 )
 
@@ -63,6 +57,5 @@ run_list(
   "role[trac]",
   "role[osqa]",
   "role[irc]",
-  "recipe[blogs]",
-  "recipe[openvpn]"
+  "recipe[blogs]"
 )
diff --git a/roles/shruikan.rb b/roles/shruikan.rb
new file mode 100644 (file)
index 0000000..0cf03ba
--- /dev/null
@@ -0,0 +1,53 @@
+name "shruikan"
+description "Master role applied to shruikan"
+
+default_attributes(
+  :hardware => {
+    :shm_size => "14g"
+  },
+  :networking => {
+    :interfaces => {
+      :external_ipv4 => {
+        :interface => "ens18",
+        :role => :external,
+        :family => :inet,
+        :address => "45.148.169.51",
+        :prefix => "25",
+        :gateway => "45.148.169.1"
+      },
+      :external_ipv6 => {
+        :interface => "ens18",
+        :role => :external,
+        :family => :inet6,
+        :address => "2a0a:aa42:56:1000::1",
+        :prefix => "48",
+        :gateway => "2a0a:aa42:56::1"
+      }
+    }
+  },
+  :squid => {
+    :version => 4,
+    :cache_mem => "10240 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
+  },
+  :nginx => {
+    :cache => {
+      :proxy => {
+        :max_size => "16384M"
+      }
+    }
+  },
+  :tilecache => {
+    :tile_parent => "netherlands.render.openstreetmap.org"
+  }
+)
+
+run_list(
+  "role[greenmini]",
+  "role[tilecache]"
+)
diff --git a/roles/simurgh.rb b/roles/simurgh.rb
deleted file mode 100644 (file)
index 6fc8757..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-name "simurgh"
-description "Master role applied to simurgh"
-
-default_attributes(
-  :networking => {
-    :interfaces => {
-      :external_ipv4 => {
-        :interface => "ens32",
-        :role => :external,
-        :family => :inet,
-        :address => "94.20.20.55",
-        :prefix => "24",
-        :gateway => "94.20.20.1"
-      }
-    }
-  },
-  :squid => {
-    :cache_mem => "6400 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
-  },
-  :tilecache => {
-    :tile_parent => "baku.render.openstreetmap.org",
-    :tile_siblings => [
-      "katie.openstreetmap.org",
-      "konqi.openstreetmap.org",
-      "ridgeback.openstreetmap.org"
-    ]
-  }
-)
-
-run_list(
-  "role[delta]",
-  "role[tilecache]"
-)
diff --git a/roles/snap-01.rb b/roles/snap-01.rb
new file mode 100644 (file)
index 0000000..1935e75
--- /dev/null
@@ -0,0 +1,45 @@
+name "snap-01"
+description "Master role applied to snap-01"
+
+default_attributes(
+  :networking => {
+    :interfaces => {
+      :internal_ipv4 => {
+        :interface => "bond0",
+        :role => :internal,
+        :family => :inet,
+        :address => "10.0.48.49",
+        :bond => {
+          :slaves => %w[eno1 eno2 eno3 eno4]
+        }
+      }
+    }
+  },
+  :postgresql => {
+    :settings => {
+      :defaults => {
+        :shared_buffers => "128GB",
+        :work_mem => "128MB",
+        :maintenance_work_mem => "2GB",
+        :effective_cache_size => "360GB",
+        :effective_io_concurrency => "256",
+        :random_page_cost => "1.1"
+      }
+    }
+  },
+  :sysctl => {
+    :postgres => {
+      :comment => "Increase shared memory for postgres",
+      :parameters => {
+        "kernel.shmmax" => 132 * 1024 * 1024 * 1024,
+        "kernel.shmall" => 132 * 1024 * 1024 * 1024 / 4096
+      }
+    }
+  }
+)
+
+run_list(
+  "role[equinix]",
+  "role[db-master]",
+  "role[db-backup]"
+)
diff --git a/roles/snap-02.rb b/roles/snap-02.rb
new file mode 100644 (file)
index 0000000..8d3a66f
--- /dev/null
@@ -0,0 +1,19 @@
+name "snap-02"
+description "Master role applied to snap-02"
+
+default_attributes(
+  :networking => {
+    :interfaces => {
+      :internal_ipv4 => {
+        :interface => "eno1.2801",
+        :role => :internal,
+        :family => :inet,
+        :address => "10.0.0.4"
+      }
+    }
+  }
+)
+
+run_list(
+  "role[ucl]"
+)
index bc2e53f7500aa4f68bf881ae4bb8261a156f87e7..559abc016ee6e2593f1e012f1caa3ad2ac950968 100644 (file)
@@ -10,7 +10,7 @@ default_attributes(
         :family => :inet,
         :address => "10.0.32.21",
         :bond => {
-          :slaves => %w[em1 em2]
+          :slaves => %w[enp3s0f0 enp3s0f1]
         }
       },
       :external_ipv4 => {
index ce41465a875584eda11554fac60638aefc2d8324..c11255de95e27e4f6ea8256a59aca9fdb01213c2 100644 (file)
@@ -10,7 +10,7 @@ default_attributes(
         :family => :inet,
         :address => "10.0.32.22",
         :bond => {
-          :slaves => %w[em1 em2]
+          :slaves => %w[enp3s0f0 enp3s0f1]
         }
       },
       :external_ipv4 => {
diff --git a/roles/stormfly-01.rb b/roles/stormfly-01.rb
deleted file mode 100644 (file)
index fc50adc..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-name "stormfly-01"
-description "Master role applied to stormfly-01"
-
-default_attributes(
-  :networking => {
-    :interfaces => {
-      :external_ipv4 => {
-        :interface => "em1",
-        :role => :external,
-        :family => :inet,
-        :address => "140.211.167.104"
-      },
-      :external_ipv6 => {
-        :interface => "em1",
-        :role => :external,
-        :family => :inet6,
-        :address => "2605:bc80:3010:700::8cde:a768"
-      }
-    }
-  }
-)
-
-run_list(
-  "role[osuosl]",
-  "role[hp-dl360-g6]",
-  "role[taginfo]"
-)
diff --git a/roles/stormfly-02.rb b/roles/stormfly-02.rb
deleted file mode 100644 (file)
index 71e6b5d..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-name "stormfly-02"
-description "Master role applied to stormfly-02"
-
-default_attributes(
-  :networking => {
-    :interfaces => {
-      :external_ipv4 => {
-        :interface => "em1",
-        :role => :external,
-        :family => :inet,
-        :address => "140.211.167.105"
-      },
-      :external_ipv6 => {
-        :interface => "em1",
-        :role => :external,
-        :family => :inet6,
-        :address => "2605:bc80:3010:700::8cde:a769"
-      }
-    }
-  },
-  :squid => {
-    :cache_mem => "21000 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
-  },
-  :tilecache => {
-    :tile_parent => "usa.render.openstreetmap.org",
-    :tile_siblings => []
-  }
-)
-
-run_list(
-  "role[osuosl]",
-  "role[hp-dl360-g6]",
-  "role[geodns]",
-  "role[tilecache]"
-)
diff --git a/roles/stormfly-03.rb b/roles/stormfly-03.rb
new file mode 100644 (file)
index 0000000..664c061
--- /dev/null
@@ -0,0 +1,34 @@
+name "stormfly-03"
+description "Master role applied to stormfly-03"
+
+default_attributes(
+  :networking => {
+    :interfaces => {
+      :external_ipv4 => {
+        :interface => "bond0",
+        :role => :external,
+        :family => :inet,
+        :address => "140.211.167.99",
+        :bond => {
+          :slaves => %w[eno1 eno2 eno3 eno4 eno49 eno50]
+        }
+      },
+      :external_ipv6 => {
+        :interface => "bond0",
+        :role => :external,
+        :family => :inet6,
+        :address => "2605:bc80:3010:700::8cd3:a763"
+      }
+    },
+    :private_address => "10.0.16.200"
+  },
+  :tilecache => {
+    :tile_parent => "corvallis.render.openstreetmap.org"
+  }
+)
+
+run_list(
+  "role[osuosl]",
+  "role[hp-g9]",
+  "role[prometheus]"
+)
diff --git a/roles/stormfly-04.rb b/roles/stormfly-04.rb
new file mode 100644 (file)
index 0000000..af518eb
--- /dev/null
@@ -0,0 +1,74 @@
+name "stormfly-04"
+description "Master role applied to stormfly-04"
+
+default_attributes(
+  :hardware => {
+    :shm_size => "38g"
+  },
+  :networking => {
+    :interfaces => {
+      :external_ipv4 => {
+        :interface => "bond0",
+        :role => :external,
+        :family => :inet,
+        :address => "140.211.167.100",
+        :bond => {
+          :slaves => %w[eno1 eno2 eno3 eno4 eno49 eno50]
+        }
+      },
+      :external_ipv6 => {
+        :interface => "bond0",
+        :role => :external,
+        :family => :inet6,
+        :address => "2605:bc80:3010:700::8cd3:a764"
+      }
+    }
+  },
+  :postgresql => {
+    :versions => ["12"],
+    :settings => {
+      :defaults => {
+        :work_mem => "300MB",
+        :maintenance_work_mem => "10GB",
+        :random_page_cost => "1.5",
+        :effective_cache_size => "60GB",
+        :fsync => "on",
+        :effective_io_concurrency => "100"
+      }
+    }
+  },
+  :nominatim => {
+    :state => "standalone",
+    :enable_backup => false,
+    :enable_git_updates => true,
+    :dbadmins => %w[lonvia tomh],
+    :dbcluster => "12/main",
+    :postgis => "2.5",
+    :flatnode_file => "/ssd/nominatim/nodes.store",
+    :logdir => "/ssd/nominatim/log",
+    :fpm_pools => {
+      "nominatim.openstreetmap.org" => {
+        :max_children => 100
+      }
+    },
+    :tablespaces => {
+      "dosm" => "/ssd/tablespaces/dosm",
+      "iosm" => "/ssd/tablespaces/iosm",
+      "dplace" => "/ssd/tablespaces/dplace",
+      "iplace" => "/ssd/tablespaces/iplace",
+      "daddress" => "/ssd/tablespaces/daddress",
+      "iaddress" => "/ssd/tablespaces/iaddress",
+      "dsearch" => "/ssd/tablespaces/dsearch",
+      "isearch" => "/ssd/tablespaces/isearch",
+      "daux" => "/ssd/tablespaces/daux",
+      "iaux" => "/ssd/tablespaces/iaux"
+    }
+  }
+)
+
+run_list(
+  "role[osuosl]",
+  "role[hp-g9]",
+  "role[geodns]",
+  "role[nominatim]"
+)
diff --git a/roles/strato.rb b/roles/strato.rb
new file mode 100644 (file)
index 0000000..5cf4445
--- /dev/null
@@ -0,0 +1,20 @@
+name "strato"
+description "Role applied to all servers at Strato"
+
+default_attributes(
+  :hosted_by => "Strato",
+  :location => "Germany"
+)
+
+override_attributes(
+  :networking => {
+    :nameservers => ["85.214.7.22", "81.169.163.106"]
+  },
+  :ntp => {
+    :servers => ["0.de.pool.ntp.org", "1.de.pool.ntp.org", "europe.pool.ntp.org"]
+  }
+)
+
+run_list(
+  "role[de]"
+)
index 877fc766a7c930c847f921a4dbe4c9a87fde6355..23a64d835784892d3a6d3bf68a779b83af3e98c7 100644 (file)
@@ -1,14 +1,6 @@
 name "supybot"
 description "Role applied to all supybot servers"
 
-default_attributes(
-  :accounts => {
-    :users => {
-      :supybot => { :status => :role }
-    }
-  }
-)
-
 run_list(
   "recipe[supybot]"
 )
index 137600f4e3559e2f7b273c5cdd7b04ced183ae2f..fc23d22f83f3c39db44b81db87057a8cf6be4477 100644 (file)
@@ -3,18 +3,7 @@ description "Role applied to all servers at szerverem.hu"
 
 default_attributes(
   :hosted_by => "szerverem.hu",
-  :location => "Budapest, Hungary",
-  :networking => {
-    :nameservers => [
-      "8.8.8.8",
-      "8.8.4.4"
-    ],
-    :roles => {
-      :external => {
-        :zone => "sz"
-      }
-    }
-  }
+  :location => "Budapest, Hungary"
 )
 
 override_attributes(
index 8645291918de796b0a19b15323b557898658e735..0e7296b336d0d186efde950effa70ba9c8ed1aee 100644 (file)
@@ -2,6 +2,10 @@ name "tabaluga"
 description "Master role applied to tabaluga"
 
 default_attributes(
+  :dhcpd => {
+    :first_address => "10.0.62.1",
+    :last_address => "10.0.62.254"
+  },
   :networking => {
     :interfaces => {
       :internal_ipv4 => {
@@ -32,5 +36,6 @@ default_attributes(
 run_list(
   "role[equinix]",
   "role[hp-g9]",
-  "role[wiki]"
+  "role[wiki]",
+  "recipe[dhcpd]"
 )
index 9da56f28c2903015501474ff6079101bc25f0a49..c7d3d5b51cd7ecdf2905d385e266be97fae9cd10 100644 (file)
@@ -8,7 +8,6 @@ default_attributes(
         :status => :administrator
       },
       :taginfo => {
-        :status => :role,
         :members => [:jochen, :tomh]
       }
     }
diff --git a/roles/takhisis.rb b/roles/takhisis.rb
new file mode 100644 (file)
index 0000000..cf02e2a
--- /dev/null
@@ -0,0 +1,54 @@
+name "takhisis"
+description "Master role applied to takhisis"
+
+default_attributes(
+  :hardware => {
+    :shm_size => "14g"
+  },
+  :networking => {
+    :interfaces => {
+      :external_ipv4 => {
+        :interface => "ens18",
+        :role => :external,
+        :family => :inet,
+        :address => "31.3.110.20",
+        :prefix => "24",
+        :gateway => "31.3.110.1"
+      },
+      :external_ipv6 => {
+        :interface => "ens18",
+        :role => :external,
+        :family => :inet6,
+        :address => "2a03:7900:111:0:31:3:110:20",
+        :prefix => "64",
+        :gateway => "fe80::225:90ff:fe5d:c1e1"
+      }
+    }
+  },
+  :squid => {
+    :version => 4,
+    :cache_mem => "10240 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
+  },
+  :nginx => {
+    :cache => {
+      :proxy => {
+        :directory => "/store/nginx-cache/proxy-cache",
+        :max_size => "65536M"
+      }
+    }
+  },
+  :tilecache => {
+    :tile_parent => "netherlands.render.openstreetmap.org"
+  }
+)
+
+run_list(
+  "role[tuxis]",
+  "role[tilecache]"
+)
index ea2dece10828260223a330d063bfedc0f3723829..8704fb679200a9065b8a967e8d95d821bdbe120b 100644 (file)
@@ -3,15 +3,7 @@ description "Role applied to all servers at Teleservice"
 
 default_attributes(
   :hosted_by => "Teleservice Skåne AB",
-  :location => "Sjöbo, Sweden",
-  :networking => {
-    :nameservers => ["8.8.8.8", "8.8.4.4"],
-    :roles => {
-      :external => {
-        :zone => "ts"
-      }
-    }
-  }
+  :location => "Sjöbo, Sweden"
 )
 
 override_attributes(
index 292232e62c8f391ac2a04d17edb49c4560e632ea..cbdab5d460c94701e2884939770da8caffff0347 100644 (file)
@@ -9,23 +9,12 @@ default_attributes(
   },
   :hosted_by => "TeraSwitch Networks",
   :location => "Pittsburgh, Pennsylvania",
-  :timezone => "EST5EDT",
-  :networking => {
-    :nameservers => [
-      "1.1.1.1",
-      "8.8.8.8"
-    ],
-    :roles => {
-      :external => {
-        :zone => "osm"
-      }
-    }
-  }
+  :timezone => "EST5EDT"
 )
 
 override_attributes(
   :ntp => {
-    :servers => ["0.us.pool.ntp.org", "1.us.pool.ntp.org", "america.pool.ntp.org"]
+    :servers => ["0.us.pool.ntp.org", "1.us.pool.ntp.org", "north-america.pool.ntp.org"]
   }
 )
 
diff --git a/roles/tetaneutral.rb b/roles/tetaneutral.rb
deleted file mode 100644 (file)
index 07a2676..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-name "tetaneutral"
-description "Role applied to all servers at Tetaneutral.net"
-
-default_attributes(
-  :accounts => {
-    :users => {
-      :tetaneutral => { :status => :administrator }
-    }
-  },
-  :hosted_by => "Tetaneutral.net",
-  :location => "Toulouse, France",
-  :networking => {
-    :nameservers => [
-      "8.8.8.8",
-      "8.8.4.4"
-    ],
-    :roles => {
-      :external => {
-        :zone => "tnn"
-      }
-    }
-  }
-)
-
-override_attributes(
-  :ntp => {
-    :servers => ["0.fr.pool.ntp.org", "1.fr.pool.ntp.org", "europe.pool.ntp.org"]
-  }
-)
-
-run_list(
-  "role[fr]"
-)
index 27bd25cf0f8a80ba84ec886b67702024650aa647..a64e6a29bec0c80b8f255fca35d73c2a19264106 100644 (file)
@@ -18,6 +18,5 @@ default_attributes(
 )
 
 run_list(
-  "role[equinix]",
-  "role[web-backend]"
+  "role[equinix]"
 )
index 09754369438317d57d24cecd7ba1bee798efa786..493ca78d5d6e8c3630fcfc239cc4d48d58f97d41 100644 (file)
@@ -18,6 +18,5 @@ default_attributes(
 )
 
 run_list(
-  "role[equinix]",
-  "role[web-backend]"
+  "role[equinix]"
 )
index 9a2393669242a85d23a8652a14d53bf90c6232ee..c856f4dc450c0252b287ca2ac71f70e6e592f3be 100644 (file)
@@ -18,6 +18,5 @@ default_attributes(
 )
 
 run_list(
-  "role[equinix]",
-  "role[web-backend]"
+  "role[equinix]"
 )
index 7afcfb3be2cb7a1d5d6033576ba8e57855747362..baf14f7f8c523f9fb6159277e05c9da7fee35d7e 100644 (file)
@@ -10,7 +10,7 @@ default_attributes(
         :family => :inet,
         :address => "10.0.32.41",
         :bond => {
-          :slaves => %w[em1 em2]
+          :slaves => %w[enp3s0f0 enp3s0f1]
         }
       }
     }
@@ -18,6 +18,5 @@ default_attributes(
 )
 
 run_list(
-  "role[bytemark]",
-  "role[web-backend]"
+  "role[bytemark]"
 )
index 7d0db0e250df50d4b853f733dcd0638bf0ff05b2..b628591111bf2a7b6476cbed41af18adaa1594f2 100644 (file)
@@ -10,7 +10,7 @@ default_attributes(
         :family => :inet,
         :address => "10.0.32.42",
         :bond => {
-          :slaves => %w[em1 em2]
+          :slaves => %w[enp3s0f0 enp3s0f1]
         }
       }
     }
@@ -18,6 +18,5 @@ default_attributes(
 )
 
 run_list(
-  "role[bytemark]",
-  "role[web-backend]"
+  "role[bytemark]"
 )
index 0004b9116c7ff463a4e09c887fcf3bb2991c3236..4b5a385858645184ac5939252b3c86c1bb1d2a88 100644 (file)
@@ -22,5 +22,6 @@ default_attributes(
 
 run_list(
   "role[ucl]",
-  "role[supermicro-x8dtt-h]"
+  "role[supermicro-x8dtt-h]",
+  "role[crm]"
 )
index 407d7991f3349c56f65dc2a82d204a3921446e58..831118c8cf4d38477e428470dab0ce966938136e 100644 (file)
@@ -5,7 +5,6 @@ default_attributes(
   :accounts => {
     :users => {
       :tile => {
-        :status => :role,
         :members => [:jburgess, :tomh]
       }
     }
@@ -20,7 +19,8 @@ default_attributes(
       :min_spare_threads => 300,
       :max_spare_threads => 1200,
       :max_connections_per_child => 0,
-      :async_request_worker_factor => 4
+      :async_request_worker_factor => 4,
+      :listen_cores_buckets_ratio => 6
     }
   },
   :munin => {
@@ -44,12 +44,16 @@ default_attributes(
         :checkpoint_segments => "60",
         :max_wal_size => "2880MB",
         :random_page_cost => "1.1",
+        :jit => "off",
         :track_activity_query_size => "16384",
         :autovacuum_vacuum_scale_factor => "0.05",
         :autovacuum_analyze_scale_factor => "0.02"
       }
     }
   },
+  :ssl => {
+    :ct_report_uri => false
+  },
   :sysctl => {
     :sockets => {
       :comment => "Increase size of connection queue",
@@ -66,40 +70,22 @@ default_attributes(
     }
   },
   :tile => {
-    :data => {
-      :simplified_land_polygons => {
-        :url => "https://osmdata.openstreetmap.de/download/simplified-land-polygons-complete-3857.zip",
-        :refresh => true
-      },
-      :simplified_water_polygons => {
-        :url => "https://osmdata.openstreetmap.de/download/simplified-water-polygons-split-3857.zip",
-        :refresh => true
-      },
-      :admin_boundaries => {
-        :url => "http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/110m/cultural/ne_110m_admin_0_boundary_lines_land.zip",
-        :directory => "ne_110m_admin_0_boundary_lines_land"
-      },
-      :land_polygons => {
-        :url => "https://osmdata.openstreetmap.de/download/land-polygons-split-3857.zip",
-        :refresh => true
-      },
-      :water_polygons => {
-        :url => "https://osmdata.openstreetmap.de/download/water-polygons-split-3857.zip",
-        :refresh => true
-      },
-      :antarctica_icesheet_polygons => {
-        :url => "https://osmdata.openstreetmap.de/download/antarctica-icesheet-polygons-3857.zip",
-        :refresh => true
-      },
-      :antarctica_icesheet_outlines => {
-        :url => "https://osmdata.openstreetmap.de/download/antarctica-icesheet-outlines-3857.zip",
-        :refresh => true
-      }
+    :database => {
+      :style_file => "/srv/tile.openstreetmap.org/styles/default/openstreetmap-carto.style",
+      :tag_transform_script => "/srv/tile.openstreetmap.org/styles/default/openstreetmap-carto.lua",
+      :external_data_script => "/srv/tile.openstreetmap.org/styles/default/scripts/get-external-data.py -c /srv/tile.openstreetmap.org/styles/default/external-data.yml",
+      :external_data_tables => %w[
+        icesheet_outlines
+        icesheet_polygons
+        ne_110m_admin_0_boundary_lines_land
+        simplified_water_polygons
+        water_polygons
+      ]
     },
     :styles => {
       :default => {
-        :repository => "git://github.com/gravitystorm/openstreetmap-carto.git",
-        :revision => "v4.23.0",
+        :repository => "https://github.com/gravitystorm/openstreetmap-carto.git",
+        :revision => "v5.3.0",
         :max_zoom => 19
       }
     }
index ee5777735e1fc8c14479fdf06527eb4e514a7695..a76af78a7f627b24e82597bc0d89ef14ed5d36b4 100644 (file)
@@ -9,12 +9,6 @@ default_attributes(
       }
     }
   },
-  :apt => {
-    :sources => ["nginx"]
-  },
-  :networking => {
-    :tcp_fastopen_key => "tile"
-  },
   :nginx => {
     :access_log => false
   },
@@ -40,13 +34,13 @@ default_attributes(
     :network_local_port_range => {
       :comment => "Increase available local port range",
       :parameters => {
-        "net.ipv4.ip_local_port_range" => "1024 65000"
+        "net.ipv4.ip_local_port_range" => "1024\t65535"
       }
     },
-    :kernel_tfo_listen_enable => {
-      :comment => "Enable TCP Fast Open for listening sockets",
+    :network_tcp_timewait_reuse => {
+      :comment => "Allow tcp timewait reuse",
       :parameters => {
-        "net.ipv4.tcp_fastopen" => 3
+        "net.ipv4.tcp_tw_reuse" => 1
       }
     },
     :squid_swappiness => {
@@ -62,6 +56,15 @@ default_attributes(
         "kernel.sched_wakeup_granularity_ns" => "15000000"
       }
     }
+  },
+  :tools => {
+    :cron => {
+      :load => {
+        :nice => 19,
+        :io_scheduling_class => "best-effort",
+        :io_scheduling_priority => 7
+      }
+    }
   }
 )
 
index 908807bbe97d7f40f6623425e66edf4077d82963..3c9710b25de36e350b83b2a044950c15a55fa74f 100644 (file)
@@ -2,9 +2,6 @@ name "toothless"
 description "Master role applied to toothless"
 
 default_attributes(
-  :hardware => {
-    :shm_size => "6g"
-  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -24,32 +21,9 @@ default_attributes(
         :gateway => "fe80::fcff:ffff:feff:ffff"
       }
     }
-  },
-  :squid => {
-    :version => 4,
-    :cache_mem => "3584 MB",
-    :cache_dir => [
-      "rock /store/squid/rock-4096 12800 swap-timeout=200 slot-size=4096 max-size=3996",
-      "rock /store/squid/rock-8192 16000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
-      "rock /store/squid/rock-16384 22400 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
-      "rock /store/squid/rock-32768 22800 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
-    ]
-  },
-  :tilecache => {
-    :tile_parent => "london.render.openstreetmap.org",
-    :tile_siblings => [
-      "saphira.openstreetmap.org",
-      "trogdor.openstreetmap.org",
-      "katie.openstreetmap.org",
-      "konqi.openstreetmap.org",
-      "ridgeback.openstreetmap.org",
-      "gorynych.openstreetmap.org"
-    ]
   }
 )
 
 run_list(
-  "role[jump]",
-  "role[geodns]",
-  "role[tilecache]"
+  "role[jump]"
 )
index 8f916ed13ebbfe65e320f86fc9658537ab3e90a7..9276c88951aa4ac980b9508d803ea2f1af5dd39a 100644 (file)
@@ -1,13 +1,6 @@
 name "trac"
 description "Role applied to all trac servers"
 
-default_attributes(
-  :accounts => {
-    :users => {
-      :trac => { :status => :role }
-    }
-  }
-)
 run_list(
   "recipe[trac]"
 )
index 5198f673205074125be30e0ca8a471f7a67a1c05..7e0c601cfb5412bbb9a04be1e1aa1cd701a67f73 100644 (file)
@@ -2,6 +2,9 @@ name "trogdor"
 description "Master role applied to trogdor"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "14g"
+  },
   :networking => {
     :interfaces => {
       :external_ipv4 => {
@@ -26,18 +29,24 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "6400 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "10240 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
+  },
+  :nginx => {
+    :cache => {
+      :proxy => {
+        :max_size => "131072M"
+      }
+    }
   },
   :tilecache => {
-    :tile_parent => "amsterdam.render.openstreetmap.org",
-    :tile_siblings => [
-      "katie.openstreetmap.org",
-      "konqi.openstreetmap.org",
-      "ridgeback.openstreetmap.org",
-      "gorynych.openstreetmap.org",
-      "simurgh.openstreetmap.org"
-    ]
+    :tile_parent => "netherlands.render.openstreetmap.org"
   }
 )
 
diff --git a/roles/tuatara.rb b/roles/tuatara.rb
deleted file mode 100644 (file)
index 02d70cd..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-name "tuatara"
-description "Master role applied to tuatara"
-
-default_attributes(
-  :networking => {
-    :interfaces => {
-      :external_ipv4 => {
-        :interface => "eno1",
-        :role => :external,
-        :family => :inet,
-        :address => "114.23.141.203",
-        :prefix => "29",
-        :gateway => "114.23.141.201"
-      }
-    }
-  },
-  :squid => {
-    :cache_mem => "7500 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
-  },
-  :tilecache => {
-    :tile_parent => "wellington.render.openstreetmap.org",
-    :tile_siblings => [
-      "waima.openstreetmap.org",
-      "balerion.openstreetmap.org",
-      "longma.openstreetmap.org"
-    ]
-  }
-)
-
-run_list(
-  "role[hostedinnz]",
-  "role[tilecache]"
-)
diff --git a/roles/tuxis.rb b/roles/tuxis.rb
new file mode 100644 (file)
index 0000000..540879d
--- /dev/null
@@ -0,0 +1,20 @@
+name "tuxis"
+description "Role applied to all servers at Tuxis"
+
+default_attributes(
+  :hosted_by => "Tuxis",
+  :location => "Ede, Netherlands"
+)
+
+override_attributes(
+  :networking => {
+    :nameservers => ["2a03:7900:2:0:31:3:104:61", "2a03:7900:2:0:31:3:104:62"]
+  },
+  :ntp => {
+    :servers => ["0.nl.pool.ntp.org", "1.nl.pool.ntp.org", "europe.pool.ntp.org"]
+  }
+)
+
+run_list(
+  "role[nl]"
+)
index c6e21bd9afb13fa9ae23f21cf88aafafb996ce39..fb1cd1b9163e9e0f143fdaf25b6d7fb9c616fba9 100644 (file)
@@ -3,6 +3,14 @@ description "Role applied to machines using the Tyan S7010 motherboard"
 
 default_attributes(
   :hardware => {
+    :hwmon => {
+      "i2c_0_0_002f" => {
+        :ignore => %w[fan3 fan4 fan5 fan6 fan7 fan8 fan9 fan10 fan11 fan12]
+      }
+    },
+    :ipmi => {
+      :excluded_sensors => [13, 14, 15, 16, 17, 18, 19, 20]
+    },
     :modules => %w[i2c_i801 jc42 w83793],
     :sensors => {
       "jc42-*" => {
index 27064ea2359a8a42a83c83705ae899c20a1b3777..a0f5331f4a6c3c49ef44059e8481bd23b5cb2c2c 100644 (file)
@@ -8,7 +8,10 @@ default_attributes(
       :internal => {
         :inet => {
           :prefix => "20",
-          :gateway => "10.0.0.3"
+          :gateway => "10.0.0.3",
+          :routes => {
+            "10.0.0.0/8" => { :via => "10.0.0.3" }
+          }
         }
       },
       :external => {
@@ -18,13 +21,16 @@ default_attributes(
           :gateway => "193.60.236.254"
         }
       }
+    },
+    :wireguard => {
+      :keepalive => 180
     }
   }
 )
 
 override_attributes(
   :networking => {
-    :nameservers => ["10.0.0.3", "8.8.8.8", "8.8.4.4"],
+    :nameservers => ["10.0.0.3", "1.1.1.1", "1.0.0.1"],
     :search => ["ucl.openstreetmap.org", "openstreetmap.org"]
   },
   :ntp => {
index 70c88a25313364e3f3c82054361b81920f7bfd72..9e783264dfb98f059d29a63a0a71ee3c59f78c3b 100644 (file)
@@ -8,18 +8,13 @@ default_attributes(
     }
   },
   :hosted_by => "Academic Computer Club, Umeå University",
-  :location => "Umeå, Sweden",
-  :networking => {
-    :nameservers => ["130.239.18.251", "130.239.18.252", "130.239.1.90"],
-    :roles => {
-      :external => {
-        :zone => "osm"
-      }
-    }
-  }
+  :location => "Umeå, Sweden"
 )
 
 override_attributes(
+  :networking => {
+    :nameservers => ["130.239.18.251", "130.239.18.252", "130.239.1.90"]
+  },
   :ntp => {
     :servers => ["0.se.pool.ntp.org", "1.se.pool.ntp.org", "europe.pool.ntp.org"]
   }
diff --git a/roles/unizar.rb b/roles/unizar.rb
deleted file mode 100644 (file)
index f9d5d12..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-name "unizar"
-description "Role applied to all servers at University of Zaragoza"
-
-default_attributes(
-  :accounts => {
-    :users => {
-      :osluz => { :status => :administrator }
-    }
-  },
-  :hosted_by => "University of Zaragoza",
-  :location => "Zaragoza, Spain",
-  :networking => {
-    :nameservers => ["155.210.12.9", "155.210.3.12"],
-    :roles => {
-      :external => {
-        :zone => "uz"
-      }
-    }
-  }
-)
-
-override_attributes(
-  :ntp => {
-    :servers => ["0.es.pool.ntp.org", "1.es.pool.ntp.org", "europe.pool.ntp.org"]
-  }
-)
-
-run_list(
-  "role[es]"
-)
index d4aca4c0ed383681c3765f2e30d7c5ff2be2044d..3d0eab25c053e3208d016550b9c80f01cb636a04 100644 (file)
@@ -3,15 +3,7 @@ description "Role applied to all servers at Ukrainian Telecommunication Group"
 
 default_attributes(
   :hosted_by => "Ukrainian Telecommunication Group",
-  :location => "Kiev, Ukraine",
-  :networking => {
-    :nameservers => ["8.8.8.8", "8.8.4.4"],
-    :roles => {
-      :external => {
-        :zone => "osm"
-      }
-    }
-  }
+  :location => "Kiev, Ukraine"
 )
 
 override_attributes(
index 8a3a91e1051103cf8799be4c2555da07a732194a..e91318a99a7c0b496682de473cc1571d38776002 100644 (file)
@@ -2,6 +2,9 @@ name "vipertooth"
 description "Master role applied to vipertooth"
 
 default_attributes(
+  :hardware => {
+    :shm_size => "18g"
+  },
   :location => "Kiev, Ukraine",
   :networking => {
     :interfaces => {
@@ -24,17 +27,17 @@ default_attributes(
     }
   },
   :squid => {
-    :cache_mem => "16000 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "16384 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
   },
   :tilecache => {
-    :tile_parent => "kiev.render.openstreetmap.org",
-    :tile_siblings => [
-      "cmok.openstreetmap.org",
-      "sarkany.openstreetmap.org",
-      "kalessin.openstreetmap.org",
-      "konqi.openstreetmap.org"
-    ]
+    :tile_parent => "kiev.render.openstreetmap.org"
   }
 )
 
index 9b0211ce50c93efa3862ce985721bcd2f7c79e3f..03bbc3c05055f8b91036a33c0d3ecf9249856720 100644 (file)
@@ -7,6 +7,9 @@ default_attributes(
       :anovak => { :status => :administrator }
     }
   },
+  :hardware => {
+    :shm_size => "36g"
+  },
   :location => "Pula, Croatia",
   :munin => {
     :allow => ["193.198.233.210"]
@@ -29,23 +32,20 @@ default_attributes(
         :prefix => "64",
         :gateway => "2001:b68:4cff:3::1"
       }
-    },
-    :nameservers => [
-      "8.8.8.8",
-      "8.8.4.4",
-      "2001:4860:4860::8888",
-      "2001:4860:4860::8844"
-    ]
+    }
   },
   :squid => {
-    :cache_mem => "28000 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
+    :version => 4,
+    :cache_mem => "32768 MB",
+    :cache_dir => [
+      "rock /store/squid/rock-4096 20000 swap-timeout=200 slot-size=4096 max-size=3996",
+      "rock /store/squid/rock-8192 25000 swap-timeout=200 slot-size=8192 min-size=3997 max-size=8092",
+      "rock /store/squid/rock-16384 35000 swap-timeout=200 slot-size=16384 min-size=8093 max-size=16284",
+      "rock /store/squid/rock-32768 45000 swap-timeout=200 slot-size=32768 min-size=16285 max-size=262144"
+    ]
   },
   :tilecache => {
-    :tile_parent => "pula.render.openstreetmap.org",
-    :tile_siblings => [
-      "drogon.openstreetmap.org"
-    ]
+    :tile_parent => "pula.render.openstreetmap.org"
   }
 )
 
diff --git a/roles/waima.rb b/roles/waima.rb
deleted file mode 100644 (file)
index 14f1154..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-name "waima"
-description "Master role applied to waima"
-
-default_attributes(
-  :networking => {
-    :interfaces => {
-      :external_ipv4 => {
-        :interface => "ens3",
-        :role => :external,
-        :family => :inet,
-        :address => "192.168.1.4",
-        :prefix => "24",
-        :gateway => "192.168.1.1",
-        :public_address => "103.197.61.160"
-      }
-    }
-  },
-  :squid => {
-    :cache_mem => "7500 MB",
-    :cache_dir => "coss /store/squid/coss-01 128000 block-size=8192 max-size=262144 membufs=80"
-  },
-  :tilecache => {
-    :tile_parent => "hamilton.render.openstreetmap.org",
-    :tile_siblings => [
-      "tuatara.openstreetmap.org",
-      "balerion.openstreetmap.org",
-      "longma.openstreetmap.org"
-    ]
-  }
-)
-
-run_list(
-  "role[catalyst]",
-  "role[tilecache]"
-)
index d59ce812e00c9608aa0301b520725e70f95477b2..a3cf9413bebdd28931e749a7342c0a8c68d9f552 100644 (file)
@@ -3,9 +3,10 @@ description "Role applied to all web/api backend servers"
 
 default_attributes(
   :apache => {
-    :mpm => "worker",
-    :worker => {
-      :max_connections_per_child => 10000
+    :mpm => "event",
+    :event => {
+      :max_connections_per_child => 10000,
+      :async_request_worker_factor => 4
     }
   },
   :logstash => {
index 3db0cc4a787d0d816d4c9086de923d7cab52dfac..c03da5277b620a825a52d96a7b4213957a92401e 100644 (file)
@@ -3,6 +3,6 @@ description "Role applied to all servers needing to find the main database"
 
 default_attributes(
   :web => {
-    :database_host => "karm.ams.openstreetmap.org"
+    :database_host => "snap-01.ams.openstreetmap.org"
   }
 )
index 0435872dd1c751b166465f04f34d76e702c9aa29..2a316491a07e6cbe1c37a54e90eb8fd3fdecae38 100644 (file)
@@ -21,8 +21,8 @@ default_attributes(
       ]
     }
   },
-  :networking => {
-    :tcp_fastopen_key => "www"
+  :memcached => {
+    :memory_limit => 4096
   },
   :passenger => {
     :max_pool_size => 50
index 3276e43e4dc8bd7fdfbec542a1057c0dc61eadd3..594c18f842334523036f53e869319eca640d7c51 100644 (file)
@@ -5,7 +5,6 @@ default_attributes(
   :accounts => {
     :users => {
       :rails => {
-        :status => :role,
         :members => [:tomh, :grant]
       }
     }
@@ -18,7 +17,7 @@ default_attributes(
   },
   :web => {
     :status => "online",
-    :memcached_servers => %w[rails1.ams rails2.ams rails3.ams]
+    :memcached_servers => %w[spike-06.ams spike-07.ams spike-08.ams]
   }
 )
 
index 845f99fe269b6d13cdf0cfc9567486725ac40557..69a8743e2dd2652491fa245960f408d623d706f0 100644 (file)
@@ -8,7 +8,7 @@ default_attributes(
     }
   },
   :apache => {
-    :mpm => "prefork",
+    :mpm => "event",
     :timeout => 30,
     :event => {
       :server_limit => 32,
@@ -18,13 +18,13 @@ default_attributes(
     }
   },
   :elasticsearch => {
-    :version => "5.x",
+    :version => "6.x",
     :cluster => {
       :name => "wiki"
     }
   },
   :exim => {
-    :trusted_users => ["www-data"],
+    :trusted_users => %w[www-data wiki],
     :aliases => {
       :root => "grant"
     },
@@ -48,8 +48,6 @@ default_attributes(
         :innodb_buffer_pool_size => "4G",
         :key_buffer_size => "64M",
         :max_connections => "200",
-        :query_cache_size => "256M",
-        :query_cache_type => "1",
         :sort_buffer_size => "8M",
         :tmp_table_size => "128M"
       }
index 0199950477e58dbd5eef915bc5557b50716c0ec3..9acde36c12daded02e1a2bb1137a443bc1101bdd 100644 (file)
@@ -6,12 +6,7 @@ default_attributes(
   :location => "Moscow, Russia",
   :timezone => "Europe/Moscow",
   :networking => {
-    :nameservers => ["8.8.8.8", "8.8.4.4"],
-    :roles => {
-      :external => {
-        :zone => "yx"
-      }
-    }
+    :wireguard => { :keepalive => 180 }
   }
 )
 
index b23b6da265744ad3d858591d789fb31560a63ae8..0428b24f8e3bc499cf25440ff5d0d868d52b3fd3 100644 (file)
@@ -2,9 +2,6 @@ name "ysera"
 description "Master role applied to ysera"
 
 default_attributes(
-  :apt => {
-    :sources => ["postgresql"]
-  },
   :networking => {
     :interfaces => {
       :internal_ipv4 => {
@@ -22,7 +19,6 @@ default_attributes(
     }
   },
   :postgresql => {
-    :versions => ["10"],
     :settings => {
       :defaults => {
         :shared_buffers => "8GB",
@@ -42,10 +38,9 @@ default_attributes(
   },
   :tile => {
     :database => {
-      :cluster => "10/main",
-      :postgis => "2.4"
+      :cluster => "12/main",
+      :postgis => "3"
     },
-    :node_file => "/store/database/nodes",
     :styles => {
       :default => {
         :tile_directories => [
index b059c5bf1bf63c50c68c106228783898da35e773..8420c54d91bd1fef2c39c22039cdf26f603982f3 100644 (file)
@@ -3,18 +3,13 @@ description "Role applied to all servers at University of West Bohemia"
 
 default_attributes(
   :hosted_by => "University of West Bohemia",
-  :location => "Pilsen, Czech Republic",
-  :networking => {
-    :nameservers => ["147.228.3.3", "147.228.52.11"],
-    :roles => {
-      :external => {
-        :zone => "osm"
-      }
-    }
-  }
+  :location => "Pilsen, Czech Republic"
 )
 
 override_attributes(
+  :networking => {
+    :nameservers => ["147.228.3.3", "147.228.52.11"]
+  },
   :ntp => {
     :servers => ["0.cz.pool.ntp.org", "1.cz.pool.ntp.org", "europe.pool.ntp.org"]
   }
diff --git a/test/data_bags/accounts/donate.json b/test/data_bags/accounts/donate.json
new file mode 100644 (file)
index 0000000..a0fdfcc
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "id": "donate",
+  "uid": "524",
+  "comment": "OSMF Donations"
+}
diff --git a/test/data_bags/accounts/git.json b/test/data_bags/accounts/git.json
new file mode 100644 (file)
index 0000000..1938a3f
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "id": "git",
+  "uid": "508",
+  "comment": "git.openstreetmap.org",
+  "home": "/var/lib/git"
+}
diff --git a/test/data_bags/accounts/gpstile.json b/test/data_bags/accounts/gpstile.json
new file mode 100644 (file)
index 0000000..3a242c4
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "id": "gpstile",
+  "uid": "519",
+  "comment": "gps-tile.openstreetmap.org",
+  "home": "/srv/gps-tile.openstreetmap.org"
+}
diff --git a/test/data_bags/accounts/kibana.json b/test/data_bags/accounts/kibana.json
new file mode 100644 (file)
index 0000000..1d2fc53
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "id": "kibana",
+  "uid": "521",
+  "comment": "Kibana",
+  "manage_home": false
+}
diff --git a/test/data_bags/accounts/lonvia.json b/test/data_bags/accounts/lonvia.json
new file mode 100644 (file)
index 0000000..1684539
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "id": "lonvia",
+  "uid": "1056",
+  "comment": "Sarah Hoffmann",
+  "email": "lonvia@example.com"
+}
diff --git a/test/data_bags/accounts/nominatim.json b/test/data_bags/accounts/nominatim.json
new file mode 100644 (file)
index 0000000..675eb77
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "id": "nominatim",
+  "uid": "518",
+  "comment": "nominatim.openstreetmap.org",
+  "home": "/srv/nominatim.openstreetmap.org"
+}
diff --git a/test/data_bags/accounts/osmbackup.json b/test/data_bags/accounts/osmbackup.json
new file mode 100644 (file)
index 0000000..2fcfd71
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "id": "osmbackup",
+  "uid": 501,
+  "comment": "Backups",
+  "home": "/store/backup",
+  "manage_home": false
+}
diff --git a/test/data_bags/accounts/osqa.json b/test/data_bags/accounts/osqa.json
new file mode 100644 (file)
index 0000000..22361d0
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "id": "osqa",
+  "uid": "510",
+  "comment": "osqa.openstreetmap.org",
+  "home": "/srv/help.openstreetmap.org"
+}
diff --git a/test/data_bags/accounts/planet.json b/test/data_bags/accounts/planet.json
new file mode 100644 (file)
index 0000000..b69305f
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "id": "planet",
+  "uid": "502",
+  "comment": "planet.openstreetmap.org"
+}
diff --git a/test/data_bags/accounts/rails.json b/test/data_bags/accounts/rails.json
new file mode 100644 (file)
index 0000000..564acef
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "id": "rails",
+  "uid": "500",
+  "comment": "Rails",
+  "manage_home": false
+}
diff --git a/test/data_bags/accounts/supybot.json b/test/data_bags/accounts/supybot.json
new file mode 100644 (file)
index 0000000..b623c99
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "id": "supybot",
+  "uid": "517",
+  "comment": "Supybot"
+}
diff --git a/test/data_bags/accounts/taginfo.json b/test/data_bags/accounts/taginfo.json
new file mode 100644 (file)
index 0000000..b74e3b0
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "id": "taginfo",
+  "uid": "520",
+  "comment": "Taginfo",
+  "manage_home": false
+}
diff --git a/test/data_bags/accounts/tile.json b/test/data_bags/accounts/tile.json
new file mode 100644 (file)
index 0000000..435cb15
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "id": "tile",
+  "uid": "515",
+  "comment": "tile.openstreetmap.org",
+  "home": "/srv/tile.openstreetmap.org"
+}
diff --git a/test/data_bags/accounts/trac.json b/test/data_bags/accounts/trac.json
new file mode 100644 (file)
index 0000000..9c89cb1
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "id": "trac",
+  "uid": "509",
+  "comment": "trac.openstreetmap.org",
+  "home": "/var/lib/trac",
+  "manage_home": false
+}
diff --git a/test/data_bags/accounts/wiki.json b/test/data_bags/accounts/wiki.json
new file mode 100644 (file)
index 0000000..0ee9618
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "id": "wiki",
+  "uid": "555",
+  "comment": "wiki.openstreetmap.org",
+  "home": "/opt/wiki",
+  "manage_home": false
+}
diff --git a/test/data_bags/accounts/wordpress.json b/test/data_bags/accounts/wordpress.json
new file mode 100644 (file)
index 0000000..a081519
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "id": "wordpress",
+  "uid": "516",
+  "comment": "Wordpress"
+}
diff --git a/test/data_bags/blog/passwords.json b/test/data_bags/blog/passwords.json
new file mode 100644 (file)
index 0000000..7db4860
--- /dev/null
@@ -0,0 +1,4 @@
+{
+  "id": "passwords",
+  "osm-blog-user": "osm-blog-password"
+}
diff --git a/test/data_bags/civicrm/passwords.json b/test/data_bags/civicrm/passwords.json
new file mode 100644 (file)
index 0000000..fda558d
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "id": "passwords",
+  "database": "database-password",
+  "admin": "admin-password",
+  "key": "key",
+  "batch": "batch"
+}
diff --git a/test/data_bags/db/passwords.json b/test/data_bags/db/passwords.json
new file mode 100644 (file)
index 0000000..f509c5f
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  "id": "passwords",
+  "openstreetmap": "openstreetmap-password",
+  "rails": "rails-password",
+  "cgimap": "cgimap-password",
+  "planetdump": "planetdump-password",
+  "planetdiff": "planetdiff-password",
+  "backup": "backup-password",
+  "gpximport": "gpximport-password",
+  "munin": "munin-password",
+  "replication": "replication-password"
+}
diff --git a/test/data_bags/db/wal-secrets.json b/test/data_bags/db/wal-secrets.json
new file mode 100644 (file)
index 0000000..6f558f2
--- /dev/null
@@ -0,0 +1,4 @@
+{
+  "id": "wal-secrets",
+  "s3_key": "s3-key"
+}
diff --git a/test/data_bags/dns/passwords.json b/test/data_bags/dns/passwords.json
new file mode 100644 (file)
index 0000000..cd7b6c9
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "id": "passwords",
+  "rsync": "rsync",
+  "statuscake": "statuscake",
+  "gandi": "gandi",
+  "cloudflare": "cloudflare"
+}
diff --git a/test/data_bags/donate/passwords.json b/test/data_bags/donate/passwords.json
new file mode 100644 (file)
index 0000000..5cfde8e
--- /dev/null
@@ -0,0 +1,4 @@
+{
+  "id": "passwords",
+  "database": "database-password"
+}
diff --git a/test/data_bags/exim/aliases.json b/test/data_bags/exim/aliases.json
new file mode 100644 (file)
index 0000000..7003ab2
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "id": "aliases",
+  "mail": {
+    "test": "test@example.com"
+  }
+}
diff --git a/test/data_bags/exim/dkim.json b/test/data_bags/exim/dkim.json
new file mode 100644 (file)
index 0000000..08b8673
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "id": "dkim",
+  "openstreetmap.org": [
+    "-----BEGIN RSA PRIVATE KEY-----",
+    "-----END RSA PRIVATE KEY-----"
+  ],
+  "osmfoundation.org": [
+    "-----BEGIN RSA PRIVATE KEY-----",
+    "-----END RSA PRIVATE KEY-----"
+  ]
+}
diff --git a/test/data_bags/geoipupdate/license-keys.json b/test/data_bags/geoipupdate/license-keys.json
new file mode 100644 (file)
index 0000000..a53c128
--- /dev/null
@@ -0,0 +1,4 @@
+{
+  "id": "license-keys",
+  "149244": "key"
+}
diff --git a/test/data_bags/letsencrypt/.gitkeep b/test/data_bags/letsencrypt/.gitkeep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/data_bags/logstash/keys.json b/test/data_bags/logstash/keys.json
new file mode 100644 (file)
index 0000000..69f7fe5
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "id": "keys",
+  "lumberjack": [
+    "-----BEGIN PRIVATE KEY-----",
+    "-----END PRIVATE KEY-----"
+  ],
+  "beats": [
+    "-----BEGIN PRIVATE KEY-----",
+    "-----END PRIVATE KEY-----"
+  ]
+}
diff --git a/test/data_bags/networking/keys.json b/test/data_bags/networking/keys.json
new file mode 100644 (file)
index 0000000..de1f901
--- /dev/null
@@ -0,0 +1,4 @@
+{
+  "id": "keys",
+  "wireguard": "cQzuTMFj9LwSTdv7YqZhwsnbP2ZYzlSiK/Bgj4A9D/o="
+}
diff --git a/test/data_bags/piwik/passwords.json b/test/data_bags/piwik/passwords.json
new file mode 100644 (file)
index 0000000..396b281
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "id": "passwords",
+  "database": "database-password",
+  "salt": "salt"
+}
diff --git a/test/data_bags/prometheus/passwords.json b/test/data_bags/prometheus/passwords.json
new file mode 100644 (file)
index 0000000..81a2ce6
--- /dev/null
@@ -0,0 +1,4 @@
+{
+  "id": "passwords",
+  "grafana_admin": "grafana_admin"
+}
diff --git a/test/data_bags/prometheus/tokens.json b/test/data_bags/prometheus/tokens.json
new file mode 100644 (file)
index 0000000..61646f7
--- /dev/null
@@ -0,0 +1,4 @@
+{
+  "id": "tokens",
+  "fastly": "fastly_token"
+}
diff --git a/test/data_bags/snmpd/communities.json b/test/data_bags/snmpd/communities.json
new file mode 100644 (file)
index 0000000..3532754
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  "id": "communities"
+}
diff --git a/test/data_bags/stateofthemap/passwords.json b/test/data_bags/stateofthemap/passwords.json
new file mode 100644 (file)
index 0000000..3ffc384
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "id": "passwords",
+  "sotm2007": "sotm2007",
+  "sotm2008": "sotm2008",
+  "sotm2009": "sotm2009",
+  "sotm2010": "sotm2010",
+  "sotm2011": "sotm2011",
+  "sotm2012": "sotm2012",
+  "sotm2016": "sotm2016"
+}
diff --git a/test/data_bags/supybot/passwords.json b/test/data_bags/supybot/passwords.json
new file mode 100644 (file)
index 0000000..4ae280f
--- /dev/null
@@ -0,0 +1,4 @@
+{
+  "id": "passwords",
+  "nickserv": "nickserv"
+}
diff --git a/test/data_bags/supybot/users.json b/test/data_bags/supybot/users.json
new file mode 100644 (file)
index 0000000..7a318dc
--- /dev/null
@@ -0,0 +1,4 @@
+{
+  "id": "users",
+  "Firefishy": "Firefishy"
+}
diff --git a/test/data_bags/tile/blocks.json b/test/data_bags/tile/blocks.json
new file mode 100644 (file)
index 0000000..7088976
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "id": "blocks",
+  "user_agents": [
+    "dummy"
+  ],
+  "referers": [
+    "https://www.example.com/"
+  ]
+}
diff --git a/test/data_bags/web/passwords.json b/test/data_bags/web/passwords.json
new file mode 100644 (file)
index 0000000..ad20fa1
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  "id": "passwords",
+  "secret_key_base": "base",
+  "potlatch2_key": "potlatch2",
+  "id_key": "id",
+  "oauth_key": "oauth",
+  "google_auth_secret": "google",
+  "facebook_auth_secret": "facebook",
+  "windowslive_auth_secret": "windowslive",
+  "github_auth_secret": "github",
+  "wikipedia_auth_secret": "wikipedia",
+  "mapquest_key": "mapquest",
+  "mapzen_valhalla_key": "mapzen-valhalla",
+  "thunderforest_key": "thunderforest",
+  "totp_key": "totp",
+  "aws_key": "aws"
+}
diff --git a/test/data_bags/web/piwik.json b/test/data_bags/web/piwik.json
new file mode 100644 (file)
index 0000000..f9b7374
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  "id": "piwik",
+  "location": "piwik",
+  "site": 100,
+  "goals": {
+    "signup": 1001,
+    "mapnik": 1002,
+    "cyclemap": 1003,
+    "transportmap": 1004,
+    "mapquest": 1005
+  }
+}
diff --git a/test/data_bags/wiki/passwords.json b/test/data_bags/wiki/passwords.json
new file mode 100644 (file)
index 0000000..109e871
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "database": "database_password",
+  "admin": "admin_password",
+  "recaptcha": "precaptcha_token",
+  "thunderforest": "thunderforest_token"
+}
index 57b0b7d86d492ddc8ebc3fea21ec272c47ec7e23..446d3b9151e31c90d581e9216378508886b402b1 100644 (file)
@@ -13,9 +13,9 @@ describe service("apache2") do
 end
 
 describe port(80) do
-  it { should be_listening }
+  it { should be_listening.with("tcp") }
 end
 
 describe port(443) do
-  it { should_not be_listening }
+  it { should be_listening.with("tcp") }
 end
index bdf529cf326eb2e361734ea24b45e678732dd32c..8986df12c2d31be57e352fae740e893c6c8c1b12 100644 (file)
@@ -13,5 +13,6 @@ describe service("bind9") do
 end
 
 describe port(53) do
-  it { should be_listening }
+  it { should be_listening.with("udp") }
+  it { should be_listening.with("tcp") }
 end
similarity index 77%
rename from test/integration/apache-ssl/serverspec/apache_spec.rb
rename to test/integration/blog/serverspec/apache_spec.rb
index 9d5268271b4f3898a2b4b9587b36dae630534146..446d3b9151e31c90d581e9216378508886b402b1 100644 (file)
@@ -13,9 +13,9 @@ describe service("apache2") do
 end
 
 describe port(80) do
-  it { should be_listening }
+  it { should be_listening.with("tcp") }
 end
 
 describe port(443) do
-  it { should be_listening }
+  it { should be_listening.with("tcp") }
 end
index 9d5268271b4f3898a2b4b9587b36dae630534146..446d3b9151e31c90d581e9216378508886b402b1 100644 (file)
@@ -13,9 +13,9 @@ describe service("apache2") do
 end
 
 describe port(80) do
-  it { should be_listening }
+  it { should be_listening.with("tcp") }
 end
 
 describe port(443) do
-  it { should be_listening }
+  it { should be_listening.with("tcp") }
 end
diff --git a/test/integration/civicrm/serverspec/apache_spec.rb b/test/integration/civicrm/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/clamav/serverspec/clamav_spec.rb b/test/integration/clamav/serverspec/clamav_spec.rb
new file mode 100644 (file)
index 0000000..ce8687e
--- /dev/null
@@ -0,0 +1,22 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("clamav-daemon") do
+  it { should be_installed }
+end
+
+describe service("clamav-daemon") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe package("clamav-freshclam") do
+  it { should be_installed }
+end
+
+describe service("clamav-freshclam") do
+  it { should be_enabled }
+  it { should be_running }
+end
diff --git a/test/integration/dhcpd/serverspec/dhcpd_spec.rb b/test/integration/dhcpd/serverspec/dhcpd_spec.rb
new file mode 100644 (file)
index 0000000..643f083
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("isc-dhcp-server") do
+  it { should be_installed }
+end
+
+describe service("isc-dhcp-server") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(67) do
+  it { should be_listening.with("udp") }
+end
diff --git a/test/integration/dmca/serverspec/apache_spec.rb b/test/integration/dmca/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/dns/serverspec/apache_spec.rb b/test/integration/dns/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/donate/serverspec/apache_spec.rb b/test/integration/donate/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/donate/serverspec/mysql_spec.rb b/test/integration/donate/serverspec/mysql_spec.rb
new file mode 100644 (file)
index 0000000..b0738f9
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("mysql-server") do
+  it { should be_installed }
+end
+
+describe service("mysql") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(3306) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/elasticsearch/serverspec/elasticsearch_spec.rb b/test/integration/elasticsearch/serverspec/elasticsearch_spec.rb
new file mode 100644 (file)
index 0000000..b4e9fa7
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("elasticsearch") do
+  it { should be_installed }
+end
+
+describe service("elasticsearch") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+# describe port(9200) do
+#  it { should be_listening.with("tcp") }
+# end
diff --git a/test/integration/exim/serverspec/exim_spec.rb b/test/integration/exim/serverspec/exim_spec.rb
new file mode 100644 (file)
index 0000000..2a6f6b2
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("exim4") do
+  it { should be_installed }
+end
+
+describe service("exim4") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(25) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/fail2ban/serverspec/fail2ban_spec.rb b/test/integration/fail2ban/serverspec/fail2ban_spec.rb
new file mode 100644 (file)
index 0000000..3e41060
--- /dev/null
@@ -0,0 +1,13 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("fail2ban") do
+  it { should be_installed }
+end
+
+describe service("fail2ban") do
+  it { should be_enabled }
+  it { should be_running }
+end
index 9d5268271b4f3898a2b4b9587b36dae630534146..446d3b9151e31c90d581e9216378508886b402b1 100644 (file)
@@ -13,9 +13,9 @@ describe service("apache2") do
 end
 
 describe port(80) do
-  it { should be_listening }
+  it { should be_listening.with("tcp") }
 end
 
 describe port(443) do
-  it { should be_listening }
+  it { should be_listening.with("tcp") }
 end
index 68e63582b83e633fca2f8ba4205186df0883611d..b0738f997f4e5af73c31abfa8152db8da6695174 100644 (file)
@@ -13,5 +13,5 @@ describe service("mysql") do
 end
 
 describe port(3306) do
-  it { should be_listening }
+  it { should be_listening.with("tcp") }
 end
diff --git a/test/integration/ftp/serverspec/vsftpd_spec.rb b/test/integration/ftp/serverspec/vsftpd_spec.rb
new file mode 100644 (file)
index 0000000..d6ed28f
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("vsftpd") do
+  it { should be_installed }
+end
+
+describe service("vsftpd") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(21) do
+  it { should be_listening.with("tcp6") }
+end
diff --git a/test/integration/git-web/serverspec/apache_spec.rb b/test/integration/git-web/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/git-web/serverspec/gitweb_spec.rb b/test/integration/git-web/serverspec/gitweb_spec.rb
new file mode 100644 (file)
index 0000000..3818bea
--- /dev/null
@@ -0,0 +1,8 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("gitweb") do
+  it { should be_installed }
+end
diff --git a/test/integration/git/serverspec/git_spec.rb b/test/integration/git/serverspec/git_spec.rb
new file mode 100644 (file)
index 0000000..b34c37d
--- /dev/null
@@ -0,0 +1,8 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("git") do
+  it { should be_installed }
+end
diff --git a/test/integration/gps-tile/serverspec/apache_spec.rb b/test/integration/gps-tile/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/gps-tile/serverspec/gpsupdate_spec.rb b/test/integration/gps-tile/serverspec/gpsupdate_spec.rb
new file mode 100644 (file)
index 0000000..bf6a3db
--- /dev/null
@@ -0,0 +1,9 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe service("gps-update") do
+  it { should be_enabled }
+  it { should be_running }
+end
diff --git a/test/integration/hot/serverspec/apache_spec.rb b/test/integration/hot/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/incron/serverspec/incron_spec.rb b/test/integration/incron/serverspec/incron_spec.rb
new file mode 100644 (file)
index 0000000..8f514be
--- /dev/null
@@ -0,0 +1,13 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("incron") do
+  it { should be_installed }
+end
+
+describe service("incron") do
+  it { should be_enabled }
+  it { should be_running }
+end
diff --git a/test/integration/irc/serverspec/apache_spec.rb b/test/integration/irc/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/kibana/serverspec/apache_spec.rb b/test/integration/kibana/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/logstash-forwarder/serverspec/filebeat_spec.rb b/test/integration/logstash-forwarder/serverspec/filebeat_spec.rb
new file mode 100644 (file)
index 0000000..6ac089a
--- /dev/null
@@ -0,0 +1,13 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("filebeat") do
+  it { should be_installed }
+end
+
+describe service("filebeat") do
+  it { should be_enabled }
+  it { should be_running }
+end
diff --git a/test/integration/logstash/serverspec/elasticsearch_spec.rb b/test/integration/logstash/serverspec/elasticsearch_spec.rb
new file mode 100644 (file)
index 0000000..b4e9fa7
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("elasticsearch") do
+  it { should be_installed }
+end
+
+describe service("elasticsearch") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+# describe port(9200) do
+#  it { should be_listening.with("tcp") }
+# end
diff --git a/test/integration/logstash/serverspec/logstash_spec.rb b/test/integration/logstash/serverspec/logstash_spec.rb
new file mode 100644 (file)
index 0000000..c339de5
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("logstash") do
+  it { should be_installed }
+end
+
+describe service("logstash") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+# describe port(5044) do
+#  it { should be_listening.with("tcp") }
+# end
diff --git a/test/integration/mail/serverspec/clamav_spec.rb b/test/integration/mail/serverspec/clamav_spec.rb
new file mode 100644 (file)
index 0000000..ce8687e
--- /dev/null
@@ -0,0 +1,22 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("clamav-daemon") do
+  it { should be_installed }
+end
+
+describe service("clamav-daemon") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe package("clamav-freshclam") do
+  it { should be_installed }
+end
+
+describe service("clamav-freshclam") do
+  it { should be_enabled }
+  it { should be_running }
+end
diff --git a/test/integration/mail/serverspec/exim_spec.rb b/test/integration/mail/serverspec/exim_spec.rb
new file mode 100644 (file)
index 0000000..2a6f6b2
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("exim4") do
+  it { should be_installed }
+end
+
+describe service("exim4") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(25) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/mail/serverspec/spamassassin_spec.rb b/test/integration/mail/serverspec/spamassassin_spec.rb
new file mode 100644 (file)
index 0000000..1276f14
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("spamassassin") do
+  it { should be_installed }
+end
+
+describe service("spamassassin") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(783) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/mailman/serverspec/apache_spec.rb b/test/integration/mailman/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/mailman/serverspec/mailman_spec.rb b/test/integration/mailman/serverspec/mailman_spec.rb
new file mode 100644 (file)
index 0000000..2d5fd35
--- /dev/null
@@ -0,0 +1,13 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("mailman") do
+  it { should be_installed }
+end
+
+describe service("mailman") do
+  it { should be_enabled }
+  it { should be_running }
+end
diff --git a/test/integration/memcached/serverspec/memcached_spec.rb b/test/integration/memcached/serverspec/memcached_spec.rb
new file mode 100644 (file)
index 0000000..26eccec
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("memcached") do
+  it { should be_installed }
+end
+
+describe service("memcached") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(11211) do
+  it { should be_listening.with("tcp") }
+end
index 57b0b7d86d492ddc8ebc3fea21ec272c47ec7e23..446d3b9151e31c90d581e9216378508886b402b1 100644 (file)
@@ -13,9 +13,9 @@ describe service("apache2") do
 end
 
 describe port(80) do
-  it { should be_listening }
+  it { should be_listening.with("tcp") }
 end
 
 describe port(443) do
-  it { should_not be_listening }
+  it { should be_listening.with("tcp") }
 end
index 5fbe38339aadbb2aff86f95986a7c4e5f29bbcdd..9d3fdd3555ac79cffc189badc1aa4cad6ca908d2 100644 (file)
@@ -13,5 +13,5 @@ describe service("munin-node") do
 end
 
 describe port(4949) do
-  it { should be_listening }
+  it { should be_listening.with("tcp6") }
 end
index 68e63582b83e633fca2f8ba4205186df0883611d..b0738f997f4e5af73c31abfa8152db8da6695174 100644 (file)
@@ -13,5 +13,5 @@ describe service("mysql") do
 end
 
 describe port(3306) do
-  it { should be_listening }
+  it { should be_listening.with("tcp") }
 end
diff --git a/test/integration/nginx/serverspec/nginx_spec.rb b/test/integration/nginx/serverspec/nginx_spec.rb
new file mode 100644 (file)
index 0000000..03901cc
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("nginx") do
+  it { should be_installed }
+end
+
+describe service("nginx") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(8050) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/nodejs/serverspec/nodejs_spec.rb b/test/integration/nodejs/serverspec/nodejs_spec.rb
new file mode 100644 (file)
index 0000000..f63cb11
--- /dev/null
@@ -0,0 +1,12 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("nodejs") do
+  it { should be_installed }
+end
+
+describe package("npm") do
+  it { should be_installed }
+end
diff --git a/test/integration/nominatim/serverspec/nginx_spec.rb b/test/integration/nominatim/serverspec/nginx_spec.rb
new file mode 100644 (file)
index 0000000..03901cc
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("nginx") do
+  it { should be_installed }
+end
+
+describe service("nginx") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(8050) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/ntp/serverspec/chronyd_spec.rb b/test/integration/ntp/serverspec/chronyd_spec.rb
new file mode 100644 (file)
index 0000000..40894b0
--- /dev/null
@@ -0,0 +1,13 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("chrony") do
+  it { should be_installed }
+end
+
+describe service("chronyd") do
+  it { should be_enabled }
+  it { should be_running }
+end
diff --git a/test/integration/openssh/serverspec/openssh_spec.rb b/test/integration/openssh/serverspec/openssh_spec.rb
new file mode 100644 (file)
index 0000000..49cfac3
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("openssh-client") do
+  it { should be_installed }
+end
+
+describe package("openssh-server") do
+  it { should be_installed }
+end
+
+describe service("ssh") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(22) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/osmosis/serverspec/osmosis_spec.rb b/test/integration/osmosis/serverspec/osmosis_spec.rb
new file mode 100644 (file)
index 0000000..93aecf0
--- /dev/null
@@ -0,0 +1,8 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe file("/usr/local/bin/osmosis") do
+  it { should be_symlink }
+end
diff --git a/test/integration/osqa/serverspec/apache_spec.rb b/test/integration/osqa/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
index 9d5268271b4f3898a2b4b9587b36dae630534146..446d3b9151e31c90d581e9216378508886b402b1 100644 (file)
@@ -13,9 +13,9 @@ describe service("apache2") do
 end
 
 describe port(80) do
-  it { should be_listening }
+  it { should be_listening.with("tcp") }
 end
 
 describe port(443) do
-  it { should be_listening }
+  it { should be_listening.with("tcp") }
 end
diff --git a/test/integration/php-apache/serverspec/apache_spec.rb b/test/integration/php-apache/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/piwik/serverspec/apache_spec.rb b/test/integration/piwik/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/planet-dump/serverspec/planetdump_spec.rb b/test/integration/planet-dump/serverspec/planetdump_spec.rb
new file mode 100644 (file)
index 0000000..ed082b9
--- /dev/null
@@ -0,0 +1,23 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe file("/opt/planet-dump-ng/planet-dump-ng") do
+  it { should be_file }
+  it { should be_executable }
+end
+
+describe file("/usr/local/bin/planetdump") do
+  it { should be_file }
+  it { should be_executable }
+end
+
+describe file("/usr/local/bin/planet-mirror-redirect-update") do
+  it { should be_file }
+  it { should be_executable }
+end
+
+describe file("/etc/cron.d/planet-dump-mirror") do
+  it { should be_file }
+end
diff --git a/test/integration/planet-notes/serverspec/planetdump_spec.rb b/test/integration/planet-notes/serverspec/planetdump_spec.rb
new file mode 100644 (file)
index 0000000..6d35a49
--- /dev/null
@@ -0,0 +1,13 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe file("/usr/local/bin/planet-notes-dump") do
+  it { should be_file }
+  it { should be_executable }
+end
+
+describe file("/etc/cron.d/planet-notes-dump") do
+  it { should be_file }
+end
diff --git a/test/integration/planet/serverspec/apache_spec.rb b/test/integration/planet/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/postgresql/serverspec/postgresql_spec.rb b/test/integration/postgresql/serverspec/postgresql_spec.rb
new file mode 100644 (file)
index 0000000..97edb60
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("postgresql-10") do
+  it { should be_installed }
+end
+
+describe service("postgresql@10-main") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(5432) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/prometheus-server/serverspec/alertmanager_spec.rb b/test/integration/prometheus-server/serverspec/alertmanager_spec.rb
new file mode 100644 (file)
index 0000000..cdad783
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("prometheus-alertmanager") do
+  it { should be_installed }
+end
+
+describe service("prometheus-alertmanager") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(9093) do
+  it { should be_listening.with("tcp6") }
+end
diff --git a/test/integration/prometheus-server/serverspec/apache_spec.rb b/test/integration/prometheus-server/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/prometheus-server/serverspec/grafana_spec.rb b/test/integration/prometheus-server/serverspec/grafana_spec.rb
new file mode 100644 (file)
index 0000000..48f8945
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("grafana-enterprise") do
+  it { should be_installed }
+end
+
+describe service("grafana-server") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(3000) do
+  it { should be_listening.with("tcp6") }
+end
diff --git a/test/integration/prometheus-server/serverspec/prometheus_spec.rb b/test/integration/prometheus-server/serverspec/prometheus_spec.rb
new file mode 100644 (file)
index 0000000..a4377ce
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("prometheus") do
+  it { should be_installed }
+end
+
+describe service("prometheus") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(9090) do
+  it { should be_listening.with("tcp6") }
+end
diff --git a/test/integration/prometheus-server/serverspec/promscale_spec.rb b/test/integration/prometheus-server/serverspec/promscale_spec.rb
new file mode 100644 (file)
index 0000000..aaedf15
--- /dev/null
@@ -0,0 +1,13 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe service("promscale") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(9201) do
+  it { should be_listening.with("tcp6") }
+end
diff --git a/test/integration/prometheus/serverspec/prometheus_node_exporter_spec.rb b/test/integration/prometheus/serverspec/prometheus_node_exporter_spec.rb
new file mode 100644 (file)
index 0000000..7a035e8
--- /dev/null
@@ -0,0 +1,13 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe service("prometheus-node-exporter") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(9100) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/rsyncd/serverspec/rsync_spec.rb b/test/integration/rsyncd/serverspec/rsync_spec.rb
new file mode 100644 (file)
index 0000000..057ec3b
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("rsync") do
+  it { should be_installed }
+end
+
+describe service("rsync") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(873) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/serverinfo/gdsnd_spec.rb b/test/integration/serverinfo/gdsnd_spec.rb
new file mode 100644 (file)
index 0000000..65adc36
--- /dev/null
@@ -0,0 +1,18 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("gdnsd") do
+  it { should be_installed }
+end
+
+describe service("gdnsd") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(53) do
+  it { should be_listening.with("udp") }
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/serverinfo/serverspec/apache_spec.rb b/test/integration/serverinfo/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/snmpd/serverspec/snmpd_spec.rb b/test/integration/snmpd/serverspec/snmpd_spec.rb
new file mode 100644 (file)
index 0000000..baed87b
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("snmpd") do
+  it { should be_installed }
+end
+
+describe service("snmpd") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(161) do
+  it { should be_listening.with("udp") }
+end
diff --git a/test/integration/spamassassin/serverspec/spamassassin_spec.rb b/test/integration/spamassassin/serverspec/spamassassin_spec.rb
new file mode 100644 (file)
index 0000000..1276f14
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("spamassassin") do
+  it { should be_installed }
+end
+
+describe service("spamassassin") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(783) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/squid/serverspec/squid_spec.rb b/test/integration/squid/serverspec/squid_spec.rb
new file mode 100644 (file)
index 0000000..a72a8b3
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("squid") do
+  it { should be_installed }
+end
+
+describe service("squid") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(3128) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(8080) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/stateofhemap/serverspec/apache_spec.rb b/test/integration/stateofhemap/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/subversion/serverspec/apache_spec.rb b/test/integration/subversion/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/subversion/serverspec/subversion_spec.rb b/test/integration/subversion/serverspec/subversion_spec.rb
new file mode 100644 (file)
index 0000000..8bbecba
--- /dev/null
@@ -0,0 +1,8 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("subversion") do
+  it { should be_installed }
+end
diff --git a/test/integration/supybot/serverspec/supybot_spec.rb b/test/integration/supybot/serverspec/supybot_spec.rb
new file mode 100644 (file)
index 0000000..e5ee252
--- /dev/null
@@ -0,0 +1,13 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("limnoria") do
+  it { should be_installed }
+end
+
+describe service("supybot") do
+  it { should be_enabled }
+  it { should be_running }
+end
diff --git a/test/integration/switch2osm/serverspec/apache_spec.rb b/test/integration/switch2osm/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/sysfs/serverspec/sysfsutils_spec.rb b/test/integration/sysfs/serverspec/sysfsutils_spec.rb
new file mode 100644 (file)
index 0000000..fde71d8
--- /dev/null
@@ -0,0 +1,13 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("sysfsutils") do
+  it { should be_installed }
+end
+
+describe service("sysfsutils") do
+  it { should be_enabled }
+  it { should be_running }
+end
diff --git a/test/integration/taginfo/serverspec/apache_spec.rb b/test/integration/taginfo/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/tile/serverspec/apache_spec.rb b/test/integration/tile/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/tilecache/serverspec/nginx_spec.rb b/test/integration/tilecache/serverspec/nginx_spec.rb
new file mode 100644 (file)
index 0000000..4122e19
--- /dev/null
@@ -0,0 +1,25 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("nginx") do
+  it { should be_installed }
+end
+
+describe service("nginx") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(8050) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/tilecache/serverspec/squid_spec.rb b/test/integration/tilecache/serverspec/squid_spec.rb
new file mode 100644 (file)
index 0000000..a72a8b3
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("squid") do
+  it { should be_installed }
+end
+
+describe service("squid") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(3128) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(8080) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/trac/serverspec/apache_spec.rb b/test/integration/trac/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/web-backend/serverspec/apache_spec.rb b/test/integration/web-backend/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/web-backend/serverspec/cgimap_spec.rb b/test/integration/web-backend/serverspec/cgimap_spec.rb
new file mode 100644 (file)
index 0000000..d91e145
--- /dev/null
@@ -0,0 +1,13 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe service("cgimap") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(8000) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/web-backend/serverspec/rails_spec.rb b/test/integration/web-backend/serverspec/rails_spec.rb
new file mode 100644 (file)
index 0000000..d02a658
--- /dev/null
@@ -0,0 +1,9 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe service("api-statistics") do
+  it { should be_enabled }
+  it { should be_running }
+end
diff --git a/test/integration/web-cgimap/serverspec/cgimap_spec.rb b/test/integration/web-cgimap/serverspec/cgimap_spec.rb
new file mode 100644 (file)
index 0000000..d91e145
--- /dev/null
@@ -0,0 +1,13 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe service("cgimap") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(8000) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/web-frontend/serverspec/apache_spec.rb b/test/integration/web-frontend/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/web-frontend/serverspec/cgimap_spec.rb b/test/integration/web-frontend/serverspec/cgimap_spec.rb
new file mode 100644 (file)
index 0000000..d91e145
--- /dev/null
@@ -0,0 +1,13 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe service("cgimap") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(8000) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/web-frontend/serverspec/memcached_spec.rb b/test/integration/web-frontend/serverspec/memcached_spec.rb
new file mode 100644 (file)
index 0000000..26eccec
--- /dev/null
@@ -0,0 +1,17 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("memcached") do
+  it { should be_installed }
+end
+
+describe service("memcached") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(11211) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/web-frontend/serverspec/rails_spec.rb b/test/integration/web-frontend/serverspec/rails_spec.rb
new file mode 100644 (file)
index 0000000..1abe820
--- /dev/null
@@ -0,0 +1,19 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe service("api-statistics") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe service("rails-jobs@mailers") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe service("rails-jobs@storage") do
+  it { should be_enabled }
+  it { should be_running }
+end
diff --git a/test/integration/web-rails/serverspec/apache_spec.rb b/test/integration/web-rails/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/web-rails/serverspec/rails_spec.rb b/test/integration/web-rails/serverspec/rails_spec.rb
new file mode 100644 (file)
index 0000000..d02a658
--- /dev/null
@@ -0,0 +1,9 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe service("api-statistics") do
+  it { should be_enabled }
+  it { should be_running }
+end
diff --git a/test/integration/wiki/serverspec/apache_spec.rb b/test/integration/wiki/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end
diff --git a/test/integration/wordpress/serverspec/apache_spec.rb b/test/integration/wordpress/serverspec/apache_spec.rb
new file mode 100644 (file)
index 0000000..446d3b9
--- /dev/null
@@ -0,0 +1,21 @@
+require "serverspec"
+
+# Required by serverspec
+set :backend, :exec
+
+describe package("apache2") do
+  it { should be_installed }
+end
+
+describe service("apache2") do
+  it { should be_enabled }
+  it { should be_running }
+end
+
+describe port(80) do
+  it { should be_listening.with("tcp") }
+end
+
+describe port(443) do
+  it { should be_listening.with("tcp") }
+end