├── README ├── configs ├── nginx │ └── puppet_lb_nginx.conf └── puppet │ └── puppet_mongrels ├── files └── install-system-wide ├── mcollective └── nrpe │ ├── mc-nrpe │ └── nrpe.rb ├── misc_ruby ├── generate_initd_file.rb └── trapper.rb ├── mon_scripts ├── haproxy_targets.rb └── memcache_mon.rb ├── pcap └── http_session_times.rb ├── puppet ├── facter │ └── ec2_facts.rb ├── gitdeploy │ └── gitdeploy.rb └── misc_scripts │ ├── genmod.rb │ └── host2haproxy.rb └── stats ├── collectd └── haproxy.rb └── parse_http_times_from_tcptrace.rb /README: -------------------------------------------------------------------------------- 1 | My publicly available DevOps stuff 2 | 3 | 4 | puppet -> puppet scripts and snippets 5 | 6 | mcollective -> useful mcollective bits 7 | -------------------------------------------------------------------------------- /configs/nginx/puppet_lb_nginx.conf: -------------------------------------------------------------------------------- 1 | user www-data; 2 | worker_processes 40; 3 | 4 | error_log /mnt/nginx_logs/error.log; 5 | pid /var/run/nginx.pid; 6 | 7 | events { 8 | worker_connections 1024; 9 | } 10 | 11 | http { 12 | 13 | access_log /mnt/nginx_logs/access.log; 14 | 15 | upstream puppet-certs { 16 | server 192.168.0.123:18140; 17 | server 192.168.0.123:18141; 18 | } 19 | 20 | upstream puppet-production { 21 | server 192.168.0.111:18140; 22 | server 192.168.0.111:18141; 23 | server 192.168.0.111:18142; 24 | server 192.168.0.112:18140; 25 | server 192.168.0.112:18141; 26 | server 192.168.0.112:18142; 27 | server 192.168.0.113:18140; 28 | server 192.168.0.113:18141; 29 | server 192.168.0.113:18142; 30 | } 31 | 32 | upstream puppet-devs { 33 | server 192.168.0.41:18140; 34 | server 192.168.0.41:18141; 35 | } 36 | 37 | server { 38 | listen 8140; 39 | 40 | ssl on; 41 | ssl_session_timeout 5m; 42 | ssl_certificate /etc/puppet/ssl/certs/puppet.example.com.pem; 43 | ssl_certificate_key /etc/puppet/ssl/private_keys/puppet.example.com.pem; 44 | ssl_client_certificate /etc/puppet/ssl/ca/ca_crt.pem; 45 | 46 | # choose any ciphers 47 | ssl_ciphers SSLv2:-LOW:-EXPORT:RC4+RSA; 48 | 49 | # allow authenticated and client without certs 50 | ssl_verify_client optional; 51 | 52 | # obey to the Puppet CRL 53 | ssl_crl /etc/puppet/ssl/ca/ca_crl.pem; 54 | 55 | root /var/tmp; 56 | 57 | access_log /mnt/nginx_logs/puppet_access.log; 58 | 59 | # Redirect all certificate requests to the localhost 60 | location ~* ^/production/certificate { 61 | proxy_pass http://puppet-certs; 62 | proxy_redirect off; 63 | proxy_set_header Host $host; 64 | proxy_set_header X-Real-IP $remote_addr; 65 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 66 | proxy_set_header X-Client-Verify $ssl_client_verify; 67 | proxy_set_header X-Client-DN $ssl_client_s_dn; 68 | proxy_set_header X-SSL-Subject $ssl_client_s_dn; 69 | proxy_set_header X-SSL-Issuer $ssl_client_i_dn; 70 | proxy_read_timeout 65; 71 | } 72 | 73 | # Redirect all certificate requests to the localhost 74 | location ~* ^/(opsguya|opsguyb)/ { 75 | proxy_pass http://puppet-devs; 76 | proxy_redirect off; 77 | proxy_set_header Host $host; 78 | proxy_set_header X-Real-IP $remote_addr; 79 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 80 | proxy_set_header X-Client-Verify $ssl_client_verify; 81 | proxy_set_header X-Client-DN $ssl_client_s_dn; 82 | proxy_set_header X-SSL-Subject $ssl_client_s_dn; 83 | proxy_set_header X-SSL-Issuer $ssl_client_i_dn; 84 | proxy_read_timeout 65; 85 | } 86 | 87 | location / { 88 | proxy_pass http://puppet-production; 89 | proxy_redirect off; 90 | proxy_set_header Host $host; 91 | proxy_set_header X-Real-IP $remote_addr; 92 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 93 | proxy_set_header X-Client-Verify $ssl_client_verify; 94 | proxy_set_header X-Client-DN $ssl_client_s_dn; 95 | proxy_set_header X-SSL-Subject $ssl_client_s_dn; 96 | proxy_set_header X-SSL-Issuer $ssl_client_i_dn; 97 | proxy_read_timeout 65; 98 | } 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /configs/puppet/puppet_mongrels: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ### BEGIN INIT INFO 3 | # Provides: scriptnamescriptname 4 | # Required-Start: $remote_fs $syslog 5 | # Required-Stop: $remote_fs $syslog 6 | # Default-Start: 2 3 4 5 7 | # Default-Stop: 0 1 6 8 | # Short-Description: Start daemon at boot time 9 | # Description: Enable service provided by daemon. 10 | ### END INIT INFO 11 | 12 | PUPPET="/usr/bin/puppet" 13 | MASTERPORT=18140 14 | MONGRELS=2 15 | 16 | if [ ! -d /var/run/puppet/mongrels ]; then 17 | mkdir -p /var/run/puppet/mongrels 18 | chown -R puppet:puppet /var/run/puppet/mongrels 19 | fi 20 | 21 | start_mongrels() { 22 | PORT=$MASTERPORT 23 | ENDPORT=$((MASTERPORT+MONGRELS)) 24 | while [ $PORT -lt $ENDPORT ]; do 25 | $PUPPET master --servertype=mongrel --masterport=${PORT} --pidfile=/var/run/puppet/mongrels/${PORT}.pid 26 | PORT=$((PORT+1)) 27 | done 28 | } 29 | 30 | stop_mongrels() { 31 | for i in `ls /var/run/puppet/mongrels/*.pid`; do 32 | dapid=`cat $i` 33 | kill $dapid 34 | if [ $? -ne "0" ] ; then 35 | echo "could not kill process $dapid" 36 | exit 1 37 | fi 38 | done 39 | } 40 | 41 | 42 | case "$1" in 43 | start) 44 | start_mongrels $MASTERPORT 45 | ;; 46 | stop) 47 | stop_mongrels 48 | ;; 49 | restart) 50 | stop_mongrels && start_mongrels $MASTERPORT 51 | ;; 52 | *) 53 | echo "run using {start|stop|restart}" 54 | exit 1 55 | ;; 56 | esac 57 | -------------------------------------------------------------------------------- /files/install-system-wide: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #################################################### 3 | # This is a quick way to install our rvm from github 4 | 5 | -------------------------------------------------------------------------------- /mcollective/nrpe/mc-nrpe: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | require 'mcollective' 4 | 5 | include MCollective::RPC 6 | 7 | #set args to break by default yo 8 | args = {:customer => "abcdefg", 9 | } 10 | 11 | options = rpcoptions do |parser, options| 12 | parser.on('-k', '--customer CUSTOMER', 'Customer') do |v| 13 | args[:customer] = v 14 | end 15 | 16 | args[:run_all] = true 17 | end 18 | 19 | mc = rpcclient("nrpe", :options => options) 20 | mc.fact_filter "mw_customer", args[:customer] 21 | mc.runall(args).each do |resp| 22 | puts "#{resp[:sender]}: #{resp[:data][:output]}" 23 | end 24 | printrpcstats 25 | 26 | -------------------------------------------------------------------------------- /mcollective/nrpe/nrpe.rb: -------------------------------------------------------------------------------- 1 | module MCollective 2 | module Agent 3 | class Nrpe "NRPE Agent", 5 | :description => "run all nrpe checks", 6 | :author => "Chris Mague", 7 | :license => "DWYWI", 8 | :version => "0.1", 9 | :url => "https://github.com/maguec/devops/mcollective/nrpe", 10 | :timeout => 300 11 | 12 | def has_nrpe() 13 | File.exists?("/etc/nagios/nrpe.cfg") 14 | end 15 | 16 | def find_configs() 17 | cfg_files = [] 18 | main_cfg = File.open("/etc/nagios/nrpe.cfg") 19 | main_cfg.readlines.each do |line| 20 | if line =~ /^include=(.*)/ 21 | cfg_files << $1 22 | end 23 | if line =~ /^include_dir=(.*)/ 24 | Dir.glob("#{$1}/*.cfg").each { |x| cfg_files << x } 25 | end 26 | end 27 | main_cfg.close 28 | cfg_files 29 | end 30 | 31 | def run_command(cmd) 32 | cmdrun = IO.popen(cmd) 33 | output = cmdrun.readlines 34 | cmdrun.close 35 | $?.to_i 36 | end 37 | 38 | def find_commands(cfgfiles) 39 | commands = {} 40 | cfgfiles.each do |cfgfile| 41 | cfg_file = File.open(cfgfile) 42 | cfg_file.readlines.each do |cline| 43 | if cline =~ /^command\[(\S+)\]\=(.*)/ 44 | commands[$1] = $2 45 | end 46 | end 47 | cfg_file.close 48 | end 49 | commands 50 | end 51 | 52 | 53 | action "runall" do 54 | unless has_nrpe 55 | reply.fail "could not find nagios config" 56 | end 57 | results = {} 58 | errors = [] 59 | commands = find_commands(find_configs) 60 | commands.each do |name, cmd| 61 | exit_code = run_command(cmd) 62 | results[name] = exit_code 63 | if exit_code > 0 64 | errors << name 65 | end 66 | end 67 | if errors.length < 1 68 | reply[:output] = "OK" 69 | else 70 | reply.fail = errors 71 | end 72 | end 73 | 74 | end 75 | end 76 | end 77 | 78 | # vi:tabstop=2:expandtab:ai:filetype=ruby 79 | -------------------------------------------------------------------------------- /misc_ruby/generate_initd_file.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby1.8 2 | ################################################################################## 3 | # == Synopsis 4 | # 5 | # blah 6 | # 7 | # == Usage 8 | # 9 | # blerg [OPTIONS] 10 | # 11 | # -h, --help: 12 | # show help 13 | 14 | require 'erb' 15 | require 'rubygems' 16 | require 'getoptlong' 17 | require 'rdoc/usage' 18 | 19 | 20 | 21 | # ERB template goes below 22 | 23 | template = ERB.new <<-EOF 24 | #!/bin/sh 25 | ### BEGIN INIT INFO 26 | # Provides: mystartup 27 | # Required-Start: $remote_fs $syslog 28 | # Required-Stop: $remote_fs $syslog 29 | # Default-Start: 2 3 4 5 30 | # Default-Stop: 0 1 6 31 | # Short-Description: Start daemon at boot time 32 | # Description: Enable service provided by daemon. 33 | ### END INIT INFO 34 | 35 | ROOTDIR=<%= rootdir %> 36 | 37 | <% if environvars != "" %> 38 | #set environment variables 39 | export <%= environvars %> 40 | <% end %> 41 | 42 | start_rails() { 43 | echo "Starting rails in $ROOTDIR" 44 | cd $ROOTDIR && script/server -e <%= railsenv %> -d -p <%= port %> <%= rootdir %>/<%= pidfile %> 45 | } 46 | 47 | stop_rails() { 48 | echo "Stopping rails in $ROOTDIR" 49 | cd $ROOTDIR && pid=`cat <%= rootdir %>/<%= pidfile %>` 50 | kill $pid 51 | if [ $? -ne "0" ] ; then 52 | echo "could not kill process $pid" 53 | exit 1 54 | fi 55 | 56 | } 57 | 58 | case $1 in 59 | start) 60 | start_rails 61 | ;; 62 | stop) 63 | stop_rails 64 | ;; 65 | restart) 66 | start_rails 67 | stop_rails 68 | ;; 69 | esac 70 | exit 0 71 | 72 | EOF 73 | 74 | ################################################################################ 75 | opts = GetoptLong.new( 76 | [ '--help', '-h', GetoptLong::NO_ARGUMENT ], 77 | [ '--root-dir', '-r', GetoptLong::REQUIRED_ARGUMENT ], 78 | [ '--pid-file', '-f', GetoptLong::REQUIRED_ARGUMENT ], 79 | [ '--rails-env', '-e', GetoptLong::REQUIRED_ARGUMENT ], 80 | [ '--port', '-p', GetoptLong::OPTIONAL_ARGUMENT ], 81 | [ '--environment-vars', '-v', GetoptLong::OPTIONAL_ARGUMENT ] 82 | ) 83 | 84 | railsenv = "production" 85 | port = 3012 86 | environvars = "" 87 | rootdir = "" 88 | pidfile = "" 89 | 90 | opts.each do |opt, arg| 91 | case opt 92 | when '--help' 93 | # TODO: fix the rdoc usage stuff 94 | # RDoc::usage 95 | # exit(0) 96 | when '--root-dir' 97 | rootdir = arg 98 | when '--pid-file' 99 | pidfile = arg 100 | when '--rails-env' 101 | railsenv = arg 102 | when '--port' 103 | port = arg.to_i 104 | when '--environment-vars' 105 | environvars = arg 106 | end 107 | end 108 | 109 | puts template.result(binding) 110 | -------------------------------------------------------------------------------- /misc_ruby/trapper.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # Find out what signal is getting sent to your process 4 | # written to understand what monit/daemontools/runit are actually doing 5 | #Signal.list #=> { 6 | # "EXIT"=>0, 7 | # "HUP"=>1, 8 | # "INT"=>2, 9 | # "QUIT"=>3, 10 | # "ILL"=>4, 11 | # "TRAP"=>5, 12 | # "IOT"=>6, 13 | # "ABRT"=>6, 14 | # "FPE"=>8, 15 | # "KILL"=>9, 16 | # "BUS"=>7, 17 | # "SEGV"=>11, 18 | # "SYS"=>31, 19 | # "PIPE"=>13, 20 | # "ALRM"=>14, 21 | # "TERM"=>15, 22 | # "URG"=>23, 23 | # "STOP"=>19, 24 | # "TSTP"=>20, 25 | # "CONT"=>18, 26 | # "CHLD"=>17, 27 | # "CLD"=>17, 28 | # "TTIN"=>21, 29 | # "TTOU"=>22, 30 | # "IO"=>29, 31 | # "XCPU"=>24, 32 | # "XFSZ"=>25, 33 | # "VTALRM"=>26, 34 | # "PROF"=>27, 35 | # "WINCH"=>28, 36 | # "USR1"=>10, 37 | # "USR2"=>12, 38 | # "PWR"=>30, 39 | # "POLL"=>29 40 | # } 41 | while 2 > 1 do 42 | Signal.trap("EXIT") do 43 | puts "EXIT" 44 | end 45 | Signal.trap("HUP") do 46 | puts "HUP" 47 | end 48 | Signal.trap("INT") do 49 | puts "INT" 50 | end 51 | Signal.trap("QUIT") do 52 | puts "QUIT" 53 | end 54 | Signal.trap("ILL") do 55 | puts "ILL" 56 | end 57 | Signal.trap("TRAP") do 58 | puts "TRAP" 59 | end 60 | Signal.trap("IOT") do 61 | puts "IOT" 62 | end 63 | Signal.trap("ABRT") do 64 | puts "ABRT" 65 | end 66 | Signal.trap("FPE") do 67 | puts "FPE" 68 | end 69 | Signal.trap("KILL") do 70 | puts "KILL" 71 | exit! 1 72 | end 73 | Signal.trap("BUS") do 74 | puts "BUS" 75 | end 76 | Signal.trap("SEGV") do 77 | puts "SEGV" 78 | end 79 | Signal.trap("SYS") do 80 | puts "SYS" 81 | end 82 | Signal.trap("PIPE") do 83 | puts "PIPE" 84 | end 85 | Signal.trap("ALRM") do 86 | puts "ALRM" 87 | end 88 | Signal.trap("TERM") do 89 | puts "TERM" 90 | end 91 | Signal.trap("URG") do 92 | puts "URG" 93 | end 94 | Signal.trap("STOP") do 95 | puts "STOP" 96 | end 97 | Signal.trap("TSTP") do 98 | puts "TSTP" 99 | end 100 | Signal.trap("CONT") do 101 | puts "CONT" 102 | end 103 | Signal.trap("CHLD") do 104 | puts "CHLD" 105 | end 106 | Signal.trap("CLD") do 107 | puts "CLD" 108 | end 109 | Signal.trap("TTIN") do 110 | puts "TTIN" 111 | end 112 | Signal.trap("TTOU") do 113 | puts "TTOU" 114 | end 115 | Signal.trap("IO") do 116 | puts "IO" 117 | end 118 | Signal.trap("XCPU") do 119 | puts "XCPU" 120 | end 121 | Signal.trap("XFSZ") do 122 | puts "XFSZ" 123 | end 124 | Signal.trap("VTALRM") do 125 | puts "VTALRM" 126 | end 127 | Signal.trap("PROF") do 128 | puts "PROF" 129 | end 130 | Signal.trap("WINCH") do 131 | puts "WINCH" 132 | end 133 | Signal.trap("USR1") do 134 | puts "USR1" 135 | end 136 | Signal.trap("USR2") do 137 | puts "USR2" 138 | end 139 | Signal.trap("PWR") do 140 | puts "PWR" 141 | end 142 | Signal.trap("POLL") do 143 | puts "POLL" 144 | end 145 | end 146 | -------------------------------------------------------------------------------- /mon_scripts/haproxy_targets.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ################################################################################# 3 | # == Synopsis 4 | # 5 | # == Usage 6 | # 7 | # haproxy.rb [OPTIONS] 8 | # 9 | # -h, --help: 10 | # Show help 11 | # 12 | # -H, --host 13 | # Haproxy Server to gather from 14 | # default is localhost 15 | # 16 | # -t, --threshold 17 | # threshold to alert for uptime 18 | # default is 60 19 | # 20 | # -P, --path 21 | # Path to statistics page in haproxy 22 | # Set in haproxy config file 23 | # 24 | # 25 | # 26 | # 27 | # -u, --user 28 | # User to login as 29 | # 30 | # -p, --password 31 | # Password for user 32 | # 33 | # -s, --stats 34 | # name of the frontend and backend you are looking to gather stats on 35 | # 36 | # 37 | # Kudos to this site for getting me up and running 38 | # http://support.rightscale.com/12-Guides/RightScale_Methodologies/Monitoring_System/Writing_custom_collectd_plugins/Custom_Collectd_Plug-ins_for_Linux 39 | 40 | 41 | 42 | require 'net/http' 43 | require 'uri' 44 | require 'csv' 45 | require 'getoptlong' 46 | #require 'rdoc/usage' 47 | 48 | PLUGIN_NAME = 'haproxystats' 49 | ################################################################################# 50 | hostname = "localhost" 51 | statspath = "/haproxy/stats;csv" 52 | statname = "live" 53 | threshold = 60 54 | user = "" 55 | pass = "" 56 | 57 | opts = GetoptLong.new( 58 | [ '--help', '-h', GetoptLong::NO_ARGUMENT ], 59 | [ '--host', '-H', GetoptLong::REQUIRED_ARGUMENT ], 60 | [ '--threshold', '-t', GetoptLong::OPTIONAL_ARGUMENT ], 61 | [ '--path', '-P', GetoptLong::OPTIONAL_ARGUMENT ], 62 | [ '--user', '-u', GetoptLong::OPTIONAL_ARGUMENT ], 63 | [ '--password', '-p', GetoptLong::OPTIONAL_ARGUMENT ], 64 | [ '--stats', '-s', GetoptLong::OPTIONAL_ARGUMENT ] 65 | ) 66 | 67 | opts.each do |opt, arg| 68 | case opt 69 | when '--help' 70 | # RDoc::usage 71 | exit(0) 72 | when '--host' 73 | hostname = arg 74 | when '--threshold' 75 | threshold = arg.to_i 76 | when '--path' 77 | statspath = arg 78 | when '--user' 79 | user = arg 80 | when '--password' 81 | pass = arg 82 | when '--stats' 83 | statname = arg 84 | end 85 | end 86 | 87 | 88 | 89 | 90 | $stdout.sync = true 91 | 92 | def collect_data(hostname, path, user, pass, statname, threshold) 93 | msg = "" 94 | status = 128 95 | url = URI.parse("http://#{hostname}#{path}") 96 | req = Net::HTTP::Get.new(url.path) 97 | if user != "" and pass != "" 98 | req.basic_auth(user, pass) 99 | end 100 | res = Net::HTTP.start(url.host, url.port) do |http| 101 | http.request(req) 102 | end 103 | if res.code == "200" 104 | status = 0 105 | CSV.parse(res.body) do |row| 106 | if row[0] == statname and row[1] !~ /[A-Z]{4,6}END/ 107 | if row[17] =~ /^UP/ and row[23].to_i > threshold 108 | msg += "#{row[1]}: OK " 109 | else 110 | msg += "#{row[1]}: NOTOK " 111 | status = 1 112 | end 113 | end 114 | end 115 | end 116 | [status, msg] 117 | end 118 | 119 | 120 | check = collect_data(hostname, statspath, user, pass, statname, threshold) 121 | puts check[1] 122 | exit!check[0] 123 | 124 | -------------------------------------------------------------------------------- /mon_scripts/memcache_mon.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ################################################################################# 4 | # == Synopsis 5 | # 6 | # == Usage 7 | # 8 | # memcache_mon.rb [OPTIONS] 9 | # --host', '-H': 10 | # Host to connect to. Defaults to 127.0.0.1 11 | # 12 | # --port', '-p': 13 | # Memcache port to connect to. Defaults to 11211 14 | # 15 | # --state-file', '-f': 16 | # File that keeps state of byte counts. Default /tmp/memcache_state 17 | # 18 | # --warn-hitrate', '-W': 19 | # Warning threshold for cache hit rate. Default 10 20 | # 21 | # --crit-hitrate', '-C': 22 | # Critical threshold for cache hit rate. Default 5 23 | # 24 | # --warn-uptime', '-u': 25 | # Warning threshold for cache uptime in seconds. Default 600 26 | # 27 | # --crit-uptime', '-U': 28 | # Critical threshold for cache uptime in seconds. Default 300 29 | # 30 | # 31 | 32 | require 'socket' 33 | require 'getoptlong' 34 | require 'rdoc/usage' 35 | 36 | #set some defaults 37 | hostname = "127.0.0.1" 38 | port = 11211 39 | exit_code = 512 40 | warn_hitrate = 10.0 41 | crit_hitrate = 5.0 42 | warn_uptime = 600 43 | crit_uptime = 300 44 | state_file = "/tmp/memcache_state" 45 | out_message = "" 46 | 47 | opts = GetoptLong.new( 48 | [ '--help', '-h', GetoptLong::NO_ARGUMENT ], 49 | [ '--port', '-p', GetoptLong::OPTIONAL_ARGUMENT ], 50 | [ '--state-file', '-f', GetoptLong::OPTIONAL_ARGUMENT ], 51 | [ '--warn-hitrate', '-W', GetoptLong::OPTIONAL_ARGUMENT ], 52 | [ '--crit-hitrate', '-C', GetoptLong::OPTIONAL_ARGUMENT ], 53 | [ '--warn-uptime', '-u', GetoptLong::OPTIONAL_ARGUMENT ], 54 | [ '--crit-uptime', '-U', GetoptLong::OPTIONAL_ARGUMENT ], 55 | [ '--host', '-H', GetoptLong::REQUIRED_ARGUMENT ] 56 | ) 57 | 58 | opts.each do |opt, arg| 59 | case opt 60 | when '--help' 61 | RDoc::usage 62 | exit(0) 63 | when '--host' 64 | hostname = arg 65 | when '--port' 66 | port = arg.to_i 67 | when '--state-file' 68 | state_file = arg 69 | when '--warn-hitrate' 70 | warn_hitrate = arg.to_f 71 | when '--crit-hitrate' 72 | crit_hitrate = arg.to_f 73 | when '--warn-uptime' 74 | warn_uptime = arg.to_i 75 | when '--crit-uptime' 76 | crit_uptime = arg.to_i 77 | end 78 | end 79 | ################################################################################# 80 | # check the sanity of warn vs. crit values 81 | if crit_uptime > warn_uptime 82 | puts "The critical warning time needs to be less than or equal to the warning uptime" 83 | exit(2) 84 | end 85 | if crit_hitrate > warn_hitrate 86 | puts "The critical warning hitrate needs to be less than or equal to the warning hitrate" 87 | exit(2) 88 | end 89 | 90 | ################################################################################# 91 | myStats = Hash.new(0) 92 | 93 | begin 94 | ks = TCPSocket.open(hostname, port) 95 | 96 | ks.puts "stats\nquit\n" 97 | while line = ks.gets 98 | if line =~ /STAT\s+(\S+)\s+([0-9\.]{1,24})/ 99 | myStats[$1.to_sym] = $2.to_f 100 | end 101 | end 102 | ks.close 103 | hitrate = 100 * myStats[:get_hits] / (myStats[:get_hits] + myStats[:get_misses]) 104 | 105 | rescue Exception => e 106 | puts "CRITICAL: #{e.message}" 107 | exit(2) 108 | end 109 | 110 | ################################################################################# 111 | #check the uptime first don't bother with any stats if it just came up 112 | 113 | if myStats[:uptime] <= crit_uptime 114 | puts "CRITICAL: Uptime is less than #{crit_uptime} seconds" 115 | exit(2) 116 | elsif myStats[:uptime] < warn_uptime 117 | puts "WARNING: Uptime is less than #{warn_uptime} seconds" 118 | exit(1) 119 | end 120 | 121 | if hitrate < crit_hitrate 122 | out_message += "CRITICAL: cache hitrate is less than #{crit_hitrate}" 123 | exit_code = 2 124 | elsif hitrate <= warn_hitrate 125 | out_message += "WARNING: cache hitrate is less than #{crit_hitrate}" 126 | exit_code = 1 127 | end 128 | 129 | ################################################################################# 130 | # check to make sure bytes are flowing in and out of memcache 131 | # write to state file 132 | if File.exists?(state_file) and File.readable?(state_file) 133 | last_bytes = File.open(state_file).read.chomp.to_i 134 | else 135 | begin 136 | File.open(state_file, 'w') { |x| x.puts "0" } 137 | last_bytes = 0 138 | rescue Exception => e 139 | puts "CRITICAL: #{state_file} error #{e.message}" 140 | exit(2) 141 | end 142 | end 143 | 144 | 145 | if myStats[:bytes_read] <= last_bytes 146 | out_message = "CRITICAL: no data flowing from memcached" 147 | exit_code = 2 148 | end 149 | 150 | begin 151 | File.open(state_file, 'w') { |x| x.puts myStats[:bytes_read] } 152 | rescue Exception => e 153 | puts "CRITICAL: #{state_file} error #{e.message}" 154 | exit(2) 155 | end 156 | 157 | ################################################################################# 158 | #p myStats 159 | #puts hitrate 160 | 161 | if out_message == "" 162 | out_message = "OK: memcache checks out" 163 | exit_code = 0 164 | end 165 | puts out_message 166 | exit(exit_code) 167 | 168 | -------------------------------------------------------------------------------- /pcap/http_session_times.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'rubygems' 4 | require 'pcaplet' 5 | 6 | # run with IP and PCAP file as arguments 7 | 8 | myip = ARGV[0] 9 | 10 | sessions = {} 11 | 12 | cap = Pcap::Capture.open_offline(ARGV[1]) 13 | cap.each_packet do |pkt| 14 | 15 | if pkt.src.to_s == myip 16 | sess_key = "#{pkt.src.to_s}:#{pkt.sport.to_s}->#{pkt.dst.to_s}:#{pkt.dport.to_s}" 17 | else 18 | sess_key = "#{pkt.dst.to_s}:#{pkt.dport.to_s}->#{pkt.src.to_s}:#{pkt.sport.to_s}" 19 | end 20 | 21 | if sessions.has_key?sess_key 22 | sessions[sess_key] << pkt 23 | else 24 | sessions[sess_key] = [ pkt ] 25 | end 26 | 27 | end 28 | 29 | cap.close 30 | 31 | sessions.each do |k, v| 32 | url = "" 33 | v.each do |pkt| 34 | if pkt.tcp_data and pkt.tcp_data =~ /^(GET|POST)\s+(\S+)/ 35 | url = $2 36 | end 37 | end 38 | if url != "/moov_check" 39 | all_times = v.collect { |x| x.time.to_f } 40 | puts "#{k}:#{url} => #{all_times.max - all_times.min}" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /puppet/facter/ec2_facts.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | require 'net/http' 4 | require 'uri' 5 | ec2_base_url = "http://169.254.169.254/latest/meta-data/" 6 | 7 | def fetch_list(myurl) 8 | list = [] 9 | begin 10 | status = Timeout::timeout(2) do 11 | url = URI.parse(myurl) 12 | list = [] 13 | res = Net::HTTP.start(url.host, url.port) {|http| 14 | http.get(url.path) 15 | } 16 | res.body.split.each do |x| 17 | if x =~ /.*\/$/ 18 | list.concat(fetch_list(myurl + x)) 19 | else 20 | list << "#{myurl}#{x}" 21 | end 22 | end 23 | end 24 | rescue 25 | list = [] 26 | rescue Timeout::Error 27 | list = [] 28 | end 29 | list 30 | end 31 | 32 | def fetch_info(myurl) 33 | url = URI.parse(myurl) 34 | res = Net::HTTP.start(url.host, url.port) {|http| 35 | http.get(url.path) 36 | } 37 | if res.code == "200" 38 | if res.body =~ /\n/ 39 | result = res.body.split("\n").join(",") 40 | else 41 | result = res.body 42 | end 43 | result 44 | end 45 | end 46 | 47 | fact_list = fetch_list(ec2_base_url) 48 | fact_list.each do |x| 49 | y = fetch_info(x) 50 | unless y == nil 51 | Facter.add("ec2_#{x.sub(ec2_base_url, "").sub("/", "_").sub("-", "_")}") do 52 | confine :virtual => "xenu" 53 | setcode do 54 | y 55 | end 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /puppet/gitdeploy/gitdeploy.rb: -------------------------------------------------------------------------------- 1 | module Puppet 2 | 3 | newtype(:gitdeploy) do 4 | @doc = "Deploy software using git. Always do a git pull and only cue the restart if the software changed" 5 | 6 | newparam(:name) do 7 | desc "just keep track of this resource" 8 | end 9 | 10 | newparam(:repo_source) do 11 | desc "where we do the git pull from" 12 | #TODO -> add regexp or URL validation 13 | end 14 | 15 | newparam(:post_install) do 16 | desc "the command to run after the git clone" 17 | end 18 | 19 | newparam(:service_restart) do 20 | desc "the command to restart the service after a code update or git clone" 21 | end 22 | # 23 | newparam(:repo_path) do 24 | desc "The filesystem path to checkout to" 25 | validate do |value| 26 | path = Pathname.new(value) 27 | unless path.absolute? 28 | raise ArgumentError, "Needs to be an absolute path #{path}" 29 | end 30 | end 31 | end 32 | 33 | newproperty(:ensure) do 34 | 35 | def retrieve 36 | if File.exists?(File.join(resource[:repo_path], ".git", "config") ) 37 | gitpull 38 | else 39 | gitclone 40 | end 41 | end 42 | 43 | def gitpull 44 | f = IO.popen("cd #{resource[:repo_path]} && /usr/bin/git pull origin ") 45 | if f.readlines[0] =~ /Already up\-to\-date\./ 46 | f.close_read 47 | :present 48 | else 49 | f.close_read 50 | :absent 51 | end 52 | end 53 | 54 | def gitclone 55 | clonewars = system("/usr/bin/git clone #{resource[:repo_source]} #{resource[:repo_path]} > /dev/null") 56 | if clonewars 57 | if resource[:post_install] 58 | postinstall 59 | end 60 | :absent 61 | else 62 | raise Puppet::Error, "Git clone of #{resource[:repo_source]} failed" 63 | end 64 | end 65 | 66 | def postinstall 67 | cmdout = system(resource[:post_install]) 68 | unless cmdout 69 | raise Puppet::Error, "unsuccessfully ran command #{resource[:post_install]}" 70 | end 71 | servicerestart 72 | :absent 73 | end 74 | 75 | def servicerestart 76 | cmdout = system(resource[:service_restart]) 77 | unless cmdout 78 | raise Puppet::Error, "unsuccessfully ran command #{resource[:service_restart]}" 79 | end 80 | :absent 81 | end 82 | 83 | newvalue :present do 84 | notice "Change to present" 85 | end 86 | 87 | newvalue :absent do 88 | notice "Change to absent" 89 | end 90 | 91 | end 92 | 93 | end 94 | end 95 | -------------------------------------------------------------------------------- /puppet/misc_scripts/genmod.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | # 3 | ############################################################################# 4 | # Quick Script to generate modes tree in 2.6.5 5 | # change the module path to where you have your git repo checked out from git 6 | # not in git?? see -> http://blog.mague.com/?p=77 7 | ############################################################################# 8 | # 9 | 10 | MODULE_PATH="#{ENV["HOME"]}/puppet_repo/modules" 11 | 12 | modname = ARGV[0] 13 | 14 | unless File.directory?MODULE_PATH 15 | puts "directory #{MODULE_PATH} does not exist" 16 | exit(1) 17 | end 18 | 19 | unless File.directory?"#{MODULE_PATH}/#{modname}" 20 | 21 | Dir.mkdir("#{MODULE_PATH}/#{modname}") 22 | 23 | ["manifests", "files", "templates"].each do |pdir| 24 | Dir.mkdir("#{MODULE_PATH}/#{modname}/#{pdir}") 25 | end 26 | 27 | outstr = "class #{modname} \{\n\n\}\n" 28 | outfile = File.open("#{MODULE_PATH}/#{modname}/manifests/init.pp", 'w') 29 | outfile.write(outstr) 30 | outfile.close 31 | 32 | end 33 | -------------------------------------------------------------------------------- /puppet/misc_scripts/host2haproxy.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # 4 | 5 | require 'erb' 6 | 7 | begin 8 | template = ERB.new(File.open(ARGV[0]).read) 9 | myhosts = File.open(ARGV[1]).readlines 10 | rescue Exception => e 11 | puts "Could not open file #{ARGV[0]} => #{e.message} " 12 | end 13 | 14 | mytargs = {} 15 | 16 | myhosts.each do |line| 17 | if line =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+(\S+)\s+USEME/ 18 | mytargs[$2] = $1 19 | end 20 | end 21 | 22 | p mytargs 23 | 24 | conf=File.open("/etc/haproxy/haproxy.cfg", 'w') 25 | conf.puts template.result(binding) 26 | conf.close 27 | -------------------------------------------------------------------------------- /stats/collectd/haproxy.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ################################################################################# 3 | # == Synopsis 4 | # 5 | # == Usage 6 | # 7 | # haproxy.rb [OPTIONS] 8 | # 9 | # -h, --help: 10 | # Show help 11 | # 12 | # -H, --host 13 | # Haproxy Server to gather from 14 | # default is localhost 15 | # 16 | # -i, --interval 17 | # Interval in seconds to collect stats for 18 | # default is 60 19 | # 20 | # -P, --path 21 | # Path to statistics page in haproxy 22 | # Set in haproxy config file 23 | # 24 | # 25 | # 26 | # 27 | # -u, --user 28 | # User to login as 29 | # 30 | # -p, --password 31 | # Password for user 32 | # 33 | # -s, --stats 34 | # name of the frontend and backend you are looking to gather stats on 35 | # 36 | # 37 | # Kudos to this site for getting me up and running 38 | # http://support.rightscale.com/12-Guides/RightScale_Methodologies/Monitoring_System/Writing_custom_collectd_plugins/Custom_Collectd_Plug-ins_for_Linux 39 | 40 | 41 | 42 | require 'net/http' 43 | require 'uri' 44 | require 'csv' 45 | require 'getoptlong' 46 | require 'rdoc/usage' 47 | 48 | PLUGIN_NAME = 'haproxystats' 49 | ################################################################################# 50 | sampling_interval = 60 51 | hostname = "localhost" 52 | statspath = "/haproxy/stats;csv" 53 | statname = "live" 54 | user = "" 55 | pass = "" 56 | 57 | opts = GetoptLong.new( 58 | [ '--help', '-h', GetoptLong::NO_ARGUMENT ], 59 | [ '--host', '-H', GetoptLong::REQUIRED_ARGUMENT ], 60 | [ '--interval', '-i', GetoptLong::OPTIONAL_ARGUMENT ], 61 | [ '--path', '-P', GetoptLong::OPTIONAL_ARGUMENT ], 62 | [ '--user', '-u', GetoptLong::OPTIONAL_ARGUMENT ], 63 | [ '--password', '-p', GetoptLong::OPTIONAL_ARGUMENT ], 64 | [ '--stats', '-s', GetoptLong::OPTIONAL_ARGUMENT ] 65 | ) 66 | 67 | opts.each do |opt, arg| 68 | case opt 69 | when '--help' 70 | RDoc::usage 71 | exit(0) 72 | when '--host' 73 | hostname = arg 74 | when '--interval' 75 | sampling_interval = arg.to_i 76 | when '--path' 77 | statspath = arg 78 | when '--user' 79 | user = arg 80 | when '--password' 81 | pass = arg 82 | when '--stats' 83 | statname = arg 84 | end 85 | end 86 | 87 | 88 | 89 | 90 | $stdout.sync = true 91 | 92 | def collect_data(hostname, path, user, pass, statname, start_run) 93 | url = URI.parse("http://#{hostname}#{path}") 94 | req = Net::HTTP::Get.new(url.path) 95 | if user != "" and pass != "" 96 | req.basic_auth(user, pass) 97 | end 98 | res = Net::HTTP.start(url.host, url.port) do |http| 99 | http.request(req) 100 | end 101 | if res.code == "200" 102 | CSV.parse(res.body) do |row| 103 | if row[0] == statname 104 | if ["FRONTEND", "BACKEND"].member?row[1] 105 | puts "PUTVAL #{hostname}/haproxy-#{row[1].downcase}/counter-sessions #{start_run}:#{row[7]}" 106 | end 107 | end 108 | end 109 | end 110 | end 111 | 112 | 113 | while true do 114 | start_run = Time.now.to_i 115 | next_run = start_run + sampling_interval 116 | collect_data(hostname, statspath, user, pass, statname, start_run) 117 | while((time_left = (next_run - Time.now.to_i)) > 0) do 118 | sleep(time_left) 119 | end 120 | end 121 | -------------------------------------------------------------------------------- /stats/parse_http_times_from_tcptrace.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | myfile = File.open(ARGV[0], "r") 4 | 5 | myfile.readlines.each do |line| 6 | if line =~ /^reqrep \S+ (\S+) \S+ (\d+\.\d+) (\d+\.\d+) (\d+\.\d+) \d+ \d+ \d+ [A-Z]{1,9} (.*)/ 7 | if $4.to_f - $2.to_f > 0.2 8 | puts "#{$1}: #{$4.to_f - $2.to_f}: #{$5}" 9 | end 10 | end 11 | end 12 | 13 | --------------------------------------------------------------------------------