Ruby – regex example

I thought i might throw out some simple examples of using regexes with ruby for when i forget

command = `mpstat -P ALL`
regex = /(?<NAME0>load)\s+average:\s+(?<NAME1>\S+),\s+(?<NAME2>\S+),\s+(?<NAME3>\S+)/x
result = command.match(regex)

# Print your regex
puts " #{result['NAME0']} #{result['NAME1']} #{result['NAME2']} #{result['NAME3']}"
#or
puts " #{result[1]} #{result[2]} #{result[3]} #{result[4]}"

annndd… something more complicated in context of something else


#!/usr/bin/env ruby
require "getopt/long"
require 'socket'

opt = Getopt::Long.getopts(
     ["--server", "-s", Getopt::REQUIRED],
     ["--port", "-p", Getopt::REQUIRED],
     ["--environment", "-e", Getopt::REQUIRED]
)

unless opt["s"] and opt["p"] and opt["e"]
  unless opt["p"] =~ /\d+/
    currentFile = File.basename(__FILE__)
    puts "usage: ./#{currentFile} -s graphiteServer -p graphitePort -e siteEnvironment"
    puts "usage: ./#{currentFile} -s someserver -p 2003 -e dev"
    exit 1
  end
end

statprefix = 'stats'
hostname = `hostname`.chomp
command = `mpstat -P ALL`
epoch = (Time.now.to_i).to_s
graphiteServer = opt["s"]
graphitePort = opt["p"]
siteEnv = opt["e"]

regexTitles = /(?<TITLEID>CPU\s.*)/x
partsTitle = command.match(regexTitles)
partsTitle = partsTitle['TITLEID'].split

regex = /(?<CPUID>all.*)/x
parts = command.match(regex)
parts = parts['CPUID'].split

hash = Hash[partsTitle.zip(parts)]
sock = TCPSocket.new(graphiteServer, graphitePort)
hash.each_pair do |title,value|
  title = title.sub(/^\%/,"")
  sock.puts "#{statprefix}.#{siteEnv}.#{hostname}.cpu.all.#{title} #{value} #{epoch}"
end
sock.close

Graphite – aggregating your second retention bucket

Make sure your storage-aggregator.py is running in order databases to compress down into 2nd and 3rd retention levels.

$ ls
league_number.wsp  user_number.wsp

Find out info on your database “league_number”
Seeing something like xFilesFactor .5 means that 50% of that time retention period has to show
if you have 10 second intervals but are only inputting once every 60 seconds then your xFilesFactor is only .2
Set the xFilesFactor = 0 if you don’t want to drop any of your data

$ /usr/local/bin/whisper-info.py league_number.wsp
maxRetention: 315360000
xFilesFactor: 0.5
aggregationMethod: average
fileSize: 63097960

Archive 0
retention: 21600
secondsPerPoint: 10
points: 2160
size: 25920
offset: 40

Archive 1
retention: 315360000
secondsPerPoint: 60
points: 5256000
size: 63072000
offset: 25960

Resize your whisper database if data is not being aggregated properly

$ /usr/local/bin/whisper-resize.py league_number.wsp
Usage: whisper-resize.py path timePerPoint:timeToStore [timePerPoint:timeToStore]*

timePerPoint and timeToStore specify lengths of time, for example:

60:1440      60 seconds per datapoint, 1440 datapoints = 1 day of retention
15m:8        15 minutes per datapoint, 8 datapoints = 2 hours of retention
1h:7d        1 hour per datapoint, 7 days of retention
12h:2y       12 hours per datapoint, 2 years of retention

If you have fucked up graphs that are truncating data on the second retention size
align them like so

$ /usr/local/bin/whisper-resize.py user_number.wsp --xFilesFactor=0 --aggregationMethod=average 10:6h 1min:10y

Make sure you set your storage-aggregation correctly and make sure it’s started

$ cp storage-aggregation.conf.example storage-aggregation.conf

$ /opt/graphite/bin/carbon-aggregator.py status
carbon-aggregator (instance a) is not running
$ /opt/graphite/bin/carbon-aggregator.py start
Starting carbon-aggregator (instance a)

Adding EBS Volumes with Opscode’s AWS cookbook

1. Download opscode’s aws cookbook and put it into your own cookbook repo

$ git clone https://github.com/opscode/cookbooks.git opscode-cookbooks
$ cp -r opscode-cookbooks/aws my-cookbooks/
$ cd my-cookbooks 

2. Create a new cookbook that will utilize the aws cookbook

$ knife cookbook create aws-tests

3. Set the cookbook to have the dependency of the opscode aws cookbook

$ vi my-cookbooks/aws-tests/metadata.rb
maintainer       "YOUR_COMPANY_NAME"
maintainer_email "YOUR_EMAIL"
license          "All rights reserved"
description      "Installs/Configures aws_tests"
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version          "0.0.1"

depends "aws"

4. Create your recipe to create and attach a new EBS volume to your ec2 instance

$ vi vi my-cookbooks/aws-tests/recipes/default.rb
# Create and attach your new EBS volume
aws_ebs_volume "new_ebs_volume" do
  aws_access_key "MYAPIKEY"
  aws_secret_access_key "MYAPIKEYSECRET"
  size 1
  device "/dev/xvdi"
  action [ :create, :attach ]
end

5. Create a filesystem and mount your new volume

# Create your partition and filesystem for ext4
bash "create_filesystem" do
  user "root"
  code <<-EOH
    parted /dev/xvdi mklabel gpt
    parted /dev/xvdi mkpart logical ext4 1 -1
    parted /dev/xvdi set 1 lvm on
    yes | parted /dev/xvdi mkpart logical ext4 1 -- "-1"
    mkfs.ext4 /dev/xvdi1
  EOH
  not_if "parted /dev/xvdi1 |grep ext4"
end


directory "/mnt/test" do
  owner "root"
  group "root"
  mode "0755"
  recursive true
end

mount "/mnt/test" do
  device "/dev/xvdi1"
  options "rw noatime"
  fstype "ext4"
  action [ :enable, :mount ]
  not_if "cat /proc/mounts |grep /mnt/test"
end

6. Add aws and aws_tests recipes to your node

$ knife node edit i-fff4f8c
{
  "chef_environment": "_default",
  "name": "i-fff4f8",
  "run_list": [
    "recipe[aws]",
    "recipe[aws_tests]"
  ],
  "normal": {
    "tags": [

    ],
  }
}

7. Run chef-client on your node

$ chef-client

Debugging knife configure -i

If you ever see something like this


root@chefserver01:/etc/chef# knife configure -i -V
Overwrite /root/.chef/knife.rb? (Y/N) y
Please enter the chef server URL: [http://chefserver01:4000]
Please enter a clientname for the new client: [root] jtran7
Please enter the existing admin clientname: [chef-webui]
Please enter the location of the existing admin client's private key: [/etc/chef/webui.pem]
Please enter the validation clientname: [chef-validator]
Please enter the location of the validation key: [/etc/chef/validation.pem]
Please enter the path to a chef repository (or leave blank):
Creating initial API user...
INFO: HTTP Request Returned 500 Internal Server Error: Connection reset by peer
ERROR: Server returned error for http://chefserver01:4000/clients, retrying 1/5 in 4s
INFO: HTTP Request Returned 409 Conflict: Client already exists
INFO: HTTP Request Returned 500 Internal Server Error: Connection reset by peer
ERROR: Server returned error for http://chefserver01:4000/clients/jtran7, retrying 1/5 in 4s
INFO: HTTP Request Returned 500 Internal Server Error: Connection reset by peer
ERROR: Server returned error for http://chefserver01:4000/clients/jtran7, retrying 2/5 in 5s

it’s likely your ampq password is incorrect in /etc/chef/server.rb

# amqp_pass sets the password for the AMQP virtual host in rabbitmq-server.
amqp_pass "testing"

If you had deleted your rabbitmq mnesia table you had to do something like this.
The word “testing” is your ampq password

sudo rabbitmqctl add_vhost /chef
sudo rabbitmqctl add_user chef testing
sudo rabbitmqctl set_permissions -p /chef chef ".*" ".*" ".*"

Clustered AMQP Rabbit-MQ

RabbitMQ already has excellent documentation at: http://www.rabbitmq.com/clustering.html

But this will be a bit more chef specific
server01 = existing chef-server
server02 = new rabbitmq server to be added to cluster

On Server01

On your existing chef-server
*I assume you’re using the latest rabbitmq and that server02 will also install matching version
Check what the cluster output looks like

root@server01:~# rabbitmqctl cluster_status
Cluster status of node rabbit@server01 ..
[{nodes,[{disc,[rabbit@server01]}]},{running_nodes,[rabbit@server01]}]
...done.

Copy your rabbitmq cookie to server02

root@server01:~# scp /var/lib/rabbitmq/.erlang.cookie root@server02:/var/lib/rabbitmq/
Are you sure you want to continue connecting (yes/no)? yes
root@server02's password: 
.erlang.cookie                                                                                        100%   20     0.0KB/s   00:00    

On Server02

Install rabbitmq

root@server02:~# echo "deb http://www.rabbitmq.com/debian/ testing main" |tee -a /etc/apt/sources.list
root@server02:~# wget http://www.rabbitmq.com/rabbitmq-signing-key-public.asc
root@server02:~# apt-key add rabbitmq-signing-key-public.asc
root@server02:~# apt-get update
root@server02:/var/chef/cache# apt-get -y install rabbitmq-server 

Delete existing mnesia database and start rabbitmq

root@server02:~# service rabbitmq-server stop
root@server02:~# rm -fr /var/lib/rabbitmq/mnesia 
root@server02:~# service rabbitmq-server start
 * Starting message broker rabbitmq-server
   ...done.

Join Server02 to Server01

root@server02:~# rabbitmqctl cluster_status
Cluster status of node rabbit@server02 ...
[{nodes,[{disc,[rabbit@server02]}]},{running_nodes,[rabbit@server02]}]
...done.
root@server02:~# rabbitmqctl stop_app
Stopping node rabbit@server02 ...
...done.
root@server02~# rabbitmqctl reset   
Resetting node rabbit@server02 ...
...done.
root@server02:~# rabbitmqctl cluster rabbit@server01 rabbit@server02
Clustering node rabbit@server02 with [rabbit@server01,rabbit@server02] ...
...done.
root@server02:~# rabbitmqctl start
root@server02:~# rabbitmqctl cluster_status
Cluster status of node rabbit@server01 ...
[{nodes,[{disc,[rabbit@server02,rabbit@server01]}]},
 {running_nodes,[rabbit@server02,rabbit@server01]}]
...done.

Verify on server01 that cluster shows up as expected

root@server01:~# rabbitmqctl cluster_status
Cluster status of node rabbit@server01 ...
[{nodes,[{disc,[rabbit@server02,rabbit@server01]}]},
 {running_nodes,[rabbit@server02,rabbit@server01]}]
...done.

Make sure chef still works

root@server01:~# knife node list

root@server01:~# knife client list
  chef-validator
  chef-webui
  root
  server01
root@server01:~# knife bootstrap -x root server02 --template-file ~/ubuntu12.04.rb 
Bootstrapping Chef on server02
Failed to authenticate root - trying password auth
Enter your password: 
server02 Updating installed gems

root@server01:~# knife node list
server02

Essential Knife Plugins for chef

Knife-Spork:
This plugin helps you control versioning of your cookbooks and also prevents you from accidently commiting things you don’t want to.

$ gem install knife-spork

https://github.com/jonlives/knife-spork

Knife-ec2:
Obviously this is a connector to ec2. I use Amazon ec2 so i am biased

$ gem install knife-ec2

https://github.com/opscode/knife-ec2/

Knife-preflight:
A preflight plugin for Chef::Knife which lets you see which nodes and roles use a particular cookbook before you upload it.

$ gem install knife-preflight

https://github.com/jonlives/knife-preflight

Knife-env-diff:
A plugin for Chef::Knife which will diff the cookbook versions of two or more environments.

$ gem install knife-env-diff

https://github.com/jgoulah/knife-env-diff

Other mentionables

Knife-slapchop:
Threaded bootstrapping of aws nodes
https://github.com/kryptek/knife-slapchop

Knife-ironfan
Cluster Deployments
https://github.com/infochimps-labs/ironfan

Search for more knife plugins:

$ gem search -r knife-

Ubuntu/Debian Preseeding with LVM

When you have your ubuntu or debian splash screen hit “tab”
then append:

auto url=http://mywebserver/mypreseed.cfg

You can use this example to bring up a quick webserver to server your preseed file: Python Simple HTTP Server

You’ll still probably be prompted for all the locale information because that is requested BEFORE debian/ubuntu loads the preseed configuration. ( yes , dumb i know ). These are the settings that don’t get pulled in.

# keyboard and locale settings
####################################################################

d-i debian-installer/locale string en_US
d-i console-keymaps-at/keymap select sg-latin1

# networking
####################################################################

d-i netcfg/disable_dhcp boolean false
d-i netcfg/get_hostname string localhost
d-i netcfg/get_domain string localdomain
d-i netcfg/choose_interface select eth0

You can get around this by rebuilding your boot cdrom or doing a pxe install that loads all the info ahead of time.

Example

auto url=http://mywebserver/mypreseed.cfg \
locale=en_US console-keymaps-at/keymap=sg-latin1 \
interface=eth0 hostname=localhost domain=localdomain --

Now for actually making your preseed config

Setup Locale info

d-i     debian-installer/locale string en_US
d-i     console-setup/ask_detect boolean false
d-i     time/zone string UTC
d-i     debian-installer/splash boolean false
d-i     debian-installer/language string en
d-i     debain-installer/country string US
d-i     console-keymaps-at/keymap select sg-latin1

Setup Your Networking

d-i     netcfg/get_nameservers  string 192.168.1.5
d-i     netcfg/get_ipaddress    string 192.168.1.10
d-i     netcfg/get_netmask      string 255.255.255.0
d-i     netcfg/get_gateway      string 192.168.1.1
d-i     netcfg/confirm_static   boolean true
d-i     netcfg/get_hostname string tempnode
d-i     netcfg/get_domain string localdomain

Setup your Repository and what directory in the repo to look for your install files

d-i     mirror/country string manual
d-i     mirror/http/hostname string http.us.debian.org
d-i     mirror/http/directory string /debian
d-i     mirror/http/proxy string

Partition Your disks and set them up as lvm

d-i partman-auto/disk string /dev/sda
d-i partman-auto/method string lvm
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/device_remove_lvm_span boolean true
d-i partman-auto/purge_lvm_from_device  boolean true
d-i partman-auto-lvm/new_vg_name string system

Setup your logical Volumes in LVM and also non-lvm partitions
This will make
* BEWARE OF YOUR FORMATTING OF THIS PART – IT IS SUPER SENSITIVE

/boot : is a bootable filesystem with 300mb and ext3
/ : Is between 10GB and grows to the end of the disk and ext3
swap : uses 200% of the size of system ram for a disk or 8GB

#d-i partman-auto/init_automatically_partition \
#  select Guided - use entire disk and set up LVM
d-i partman-auto/expert_recipe string                         \
      boot-root ::                                            \
              40 300 300 ext3                                 \
                      $primary{ }                             \
                      $bootable{ }                            \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext3 }    \
                      mountpoint{ /boot }                     \
              .                                               \
              2000 10000 1000000000 ext3                      \
                      $lvmok{ }                               \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext3 }    \
                      mountpoint{ / }                         \
              .                                               \
              8000 8000 200% linux-swap                       \
                      $lvmok{ }                               \
                      method{ swap } format{ }                \
              .

Here’s another LVM Example

d-i partman-auto/expert_recipe string                         \
      boot-root ::                                            \
              40 300 300 ext4                                 \
                      $primary{ }                             \
                      $bootable{ }                            \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext4 }    \
                      mountpoint{ /boot }                     \
              .                                               \
              2000 10000 1000000000 ext4                      \
                      $lvmok{ }                               \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext4 }    \
                      mountpoint{ / }                         \
              .                                               \
              2000 1000 10000 ext4                            \
                      $lvmok{ }                               \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext4 }    \
                      mountpoint{ /var }                      \
              .                                               \
              2000 1000 60000 ext4                            \
                      $lvmok{ }                               \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext4 }    \
                      mountpoint{ /var/lib/mysql }                      \
              .                                               \
              2000 1000 30000 ext4                            \
                      $lvmok{ }                               \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext4 }    \
                      mountpoint{ /www }                      \
              .                                               \
              8000 8000 200% linux-swap                       \
                      $lvmok{ }                               \
                      method{ swap } format{ }                \
              .

Answer yes to all the partition and LVM prompts

d-i partman-lvm/confirm boolean true
d-i partman/confirm_write_new_label boolean true
d-i partman/choose_partition select Finish partitioning and write changes to disk
d-i partman/confirm boolean true

Setup your Time Zone info

d-i     clock-setup/utc boolean true
d-i     clock-setup/ntp boolean true
d-i     clock-setup/ntp-server  string ntp.ubuntu.com
d-i     time/zone string US/Los_Angeles

Setup Root and First User info

d-i     base-installer/kernel/image     string linux-server
d-i     passwd/root-login       boolean true
d-i     passwd/root-password-crypted    password $1$VuPOoDRD$seX.C54E8TUdMkaAmKvjx0
d-i     passwd/user-fullname string Ubuntu User
d-i     passwd/username string ubuntu
d-i     passwd/user-password-crypted password $1$NvFY8IuR$BGqOozSN91ljvQB.pVLDw.
d-i     user-setup/encrypt-home boolean false
d-i     user-setup/allow-password-weak  boolean true
d-i     passwd/user-default-groups      string adm cdrom dialout lpadmin plugdev sambashare

Miscellaneous Stuffage

d-i     apt-setup/services-select       multiselect security
d-i     debian-installer/allow_unauthenticated  string true
d-i     pkgsel/upgrade  select safe-upgrade
d-i     pkgsel/language-packs   multiselect
d-i     pkgsel/update-policy    select none
d-i     pkgsel/updatedb boolean true
popularity-contest popularity-contest/participate boolean false
tasksel tasksel/first multiselect standard, openssh-server
d-i     grub-installer/skip     boolean false
d-i     lilo-installer/skip     boolean false
d-i     grub-installer/only_debian      boolean true
d-i     grub-installer/with_other_os    boolean false
d-i     finish-install/keep-consoles    boolean false
d-i     finish-install/reboot_in_progress       note
d-i     cdrom-detect/eject      boolean true
d-i     debian-installer/exit/halt      boolean false
d-i     debian-installer/exit/poweroff  boolean false

Choose your packages to install

d-i     pkgsel/include string vim openssh-server

What it looks like as one file:

d-i     debian-installer/locale string en_US
d-i     console-setup/ask_detect boolean false
d-i     time/zone string UTC
d-i     debian-installer/splash boolean false
d-i     debian-installer/language string en
d-i     debain-installer/country string US
d-i     netcfg/get_nameservers  string 192.168.1.5
d-i     netcfg/get_ipaddress    string 192.168.1.10
d-i     netcfg/get_netmask      string 255.255.255.0
d-i     netcfg/get_gateway      string 192.168.1.1
d-i     netcfg/confirm_static   boolean true
d-i     netcfg/get_hostname string tempnode
d-i     mirror/country string manual
d-i     mirror/http/hostname string http.us.debian.org
d-i     mirror/http/directory string /debian
d-i     mirror/http/proxy string
d-i partman-auto/disk string /dev/sda
d-i partman-auto/method string lvm
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/device_remove_lvm_span boolean true
d-i partman-auto/purge_lvm_from_device  boolean true
d-i partman-auto-lvm/new_vg_name string system
#d-i partman-auto/init_automatically_partition \
#  select Guided - use entire disk and set up LVM
d-i partman-auto/expert_recipe string                         \
      boot-root ::                                            \
              40 300 300 ext3                                 \
                      $primary{ }                             \
                      $bootable{ }                            \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext3 }    \
                      mountpoint{ /boot }                     \
              .                                               \
              2000 10000 1000000000 ext3                      \
                      $lvmok{ }                               \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext3 }    \
                      mountpoint{ / }                         \
              .                                               \
              8000 8000 200% linux-swap                       \
                      $lvmok{ }                               \
                      method{ swap } format{ }                \
              .

d-i partman-lvm/confirm boolean true
d-i partman/confirm_write_new_label boolean true
d-i partman/choose_partition select Finish partitioning and write changes to disk
d-i partman/confirm boolean true
d-i     clock-setup/utc boolean true
d-i     clock-setup/ntp boolean true
d-i     clock-setup/ntp-server  string ntp.ubuntu.com
d-i     time/zone string US/Los_Angeles
d-i     base-installer/kernel/image     string linux-server
d-i     base-installer/kernel/image     string linux-server
d-i     passwd/root-login       boolean true
d-i     passwd/root-password-crypted    password $1$VuPOoDRD$seX.C54E8TUdMkaAmKvjx0
d-i     passwd/user-fullname string Ubuntu User
d-i     user-setup/allow-password-weak  boolean true
d-i     user-setup/encrypt-home boolean false
d-i     passwd/user-default-groups      string adm cdrom dialout lpadmin plugdev sambashare
d-i     apt-setup/services-select       multiselect security
d-i     debian-installer/allow_unauthenticated  string true
d-i     pkgsel/upgrade  select safe-upgrade
d-i     pkgsel/language-packs   multiselect
d-i     pkgsel/update-policy    select none
d-i     pkgsel/updatedb boolean true
popularity-contest popularity-contest/participate boolean false
tasksel tasksel/first multiselect standard, openssh-server
d-i     grub-installer/skip     boolean false
d-i     lilo-installer/skip     boolean false
d-i     grub-installer/only_debian      boolean true
d-i     grub-installer/with_other_os    boolean false
d-i     finish-install/keep-consoles    boolean false
d-i     finish-install/reboot_in_progress       note
d-i     cdrom-detect/eject      boolean true
d-i     debian-installer/exit/halt      boolean false
d-i     debian-installer/exit/poweroff  boolean false
d-i     pkgsel/include string vim openssh-server

Info for this was stolen here ( Thanks ):
http://cptyesterday.wordpress.com/2012/06/17/notes-on-using-expert_recipe-in-debianubuntu-preseed-files/

Preseed Example files found here:

https://github.com/cookingclouds/Preseed

Graphite Install

*this assumes debian or ubuntu

Graphite Cookbook Install

$ git clone https://github.com/cookingclouds/cookbooks/tree/master/cc_graphite

I Know there is a cookbook for graphite in the opscode repo but it has dependencies.
This cookbook shouldn’t have dependencies and is also a lot more messy
Run after installing cookbook :

$ /opt/graphite/bin/carbon-cache.py start
$ cd /opt/graphite/webapp/graphite && python manage.py createsuperuser

Manual Install

Grab the sourcecode


$ wget https://launchpad.net/graphite/0.9/0.9.10/+download/graphite-web-0.9.10.tar.gz
$ wget https://launchpad.net/graphite/0.9/0.9.10/+download/carbon-0.9.10.tar.gz
$ wget https://launchpad.net/graphite/0.9/0.9.10/+download/whisper-0.9.10.tar.gz
$ wget https://launchpad.net/graphite/0.9/0.9.10/+download/check-dependencies.py

Install Whisper Database

$ ls |grep tar |while read i ; do tar xzvf $i ; done
$ apt-get -y install apache2 python-django python-django-tagging python-ldap python-memcache python-cairo
$ cd ~/whisper-0.9.10/
$ python setup.py install

Install Carbon

$ apt-get -y install python-twisted python-simplejson
$ cd ~/carbon-0.9.10/
$ python setup.py install
$ cd /opt/graphite/conf/
$ cp carbon.conf.example carbon.conf
$ cp storage-schemas.conf.example storage-schemas.conf
$ cd /opt/graphite/
$ ./bin/carbon-cache.py start

Install Graphite-web

$ cd ~/graphite-web-0.9.10/
$ python check-dependencies.py
$ python setup.py install
$ cp examples/example-graphite-vhost.conf /etc/apache2/sites-available/default
$ cp /opt/graphite/conf/graphite.wsgi.example /opt/graphite/conf/graphite.wsgi
$ mkdir /etc/apache2/run
$ apt-get -y install libapache2-mod-wsgi
$ /etc/init.d/apache2 reload
$ cd /opt/graphite/webapp/graphite/
$ python manage.py syncdb
$ chown -R www-data:www-data /opt/graphite/storage
$ cd /opt/graphite/webapp/graphite
$ cp local_settings.py.example local_settings.py
$ /etc/init.d/apache2 restart

Examples on how to send data to graphite

hostname = * you guessed it
test_001 = service name
1001 = value
$NOW = epoch time to input in graph

$ NOW=`date +%s` ; echo "hostname.test_001 1001 $NOW" |nc localhost 2003

or

$ cd /opt/graphite/examples
$ ./example-client.py

Migrating Chef CouchDB to Multi-Master CouchDB

* assuming you are using ubuntu/debian
chef-server = 192.168.1.10
couchdb01 = 192.168.1.11
couchdb02 = 192.168.1.12

Enable chef-server couchdb to listen on all interfaces

root@chefserver:~# sed -i bak s/bind_address = 127.0.0.1/bind_address = 0.0.0.0/g /etc/couchdb/default.ini
root@chefserver:~# /etc/init.d/couchdb restart

Install CouchDB on couchdb01/couchdb02 and set to listen on all interfaces

root@couchdb01:~# apt-get -y install couchdb
root@couchdb01:~# /etc/init.d/couchdb stop
root@couchdb01:~# sed -i bak s/bind_address = 127.0.0.1/bind_address = 0.0.0.0/g /etc/couchdb/default.ini
root@couchdb01:~# /etc/init.d/couchdb start

Create the empty chef table on couchdb01/couchdb02

root@couchdb01:~# curl -X PUT http://localhost:5984/chef
{"ok":true}

root@couchdb02:~# curl -X PUT http://localhost:5984/chef
{"ok":true}

Push the chef table from chef-server to couchdb01/02 and enable a continuous replication

To Couchdb02

root@chef-server:/var/lib/couchdb# curl -X POST http://localhost:5984/_replicate -H "Content-Type: application/json" -d '{"source":"chef","target":"http://192.168.1.12:5984/chef","continuous":true}'
{"ok":true,"_local_id":"77f057c373dca43097fac542c367b24f"}

To Couchdb01

root@chef-server:~# curl -X POST http://localhost:5984/_replicate -H "Content-Type: application/json" -d '{"source":"chef","target":"http://192.168.1.11:5984/chef","continuous":true}'
{"ok":true,"_local_id":"e926c9297e5776db862ae3c1be27bbde"}

Setup the multi-master replication for couchdb01/02

Enable continuous replication FROM couchdb01 to couchdb02

root@couchdb01:/var/lib/couchdb# curl -X POST http://localhost:5984/_replicate -H "Content-Type: application/json" -d '{"source":"chef","target":"http://192.168.1.12:5984/chef","continuous":true}'
{"ok":true,"_local_id":"77f057c373dca43097fac542c367b24f"}

Enable continuous replication FROM couchdb02 to couchdb01

root@couchdb02:/var/lib/couchdb# curl -X POST http://localhost:5984/_replicate -H "Content-Type: application/json" -d '{"source":"chef","target":"http://192.168.1.11:5984/chef","continuous":true}'
{"ok":true,"_local_id":"77f057c373dca43097fac542c367b24f"}

Install Apache and generate config on Chef Server

root@chefserver:~# apt-get -y install apache2
root@chefserver:~# mkdir -p /usr/share/chef-server/public
root@chefserver:~# for i in rewrite proxy status proxy_http proxy_balancer headers ; do a2enmod $i ; done
root@chefserver:~# cd /etc/apache2/sites-available
root@chefserver:~# echo "Listen 5984" | tee -a chef_couchdb_loadbalancer
root@chefserver:~# echo '<VirtualHost *:5984>' | tee -a chef_couchdb_loadbalancer
root@chefserver:~# MYHOST=$(hostname -f)
root@chefserver:~# echo "ServerName ${MYHOST}-couchdb" |tee -a chef_couchdb_loadbalancer
root@chefserver:~# cat>>chef_couchdb_loadbalancer<<EOF
<Proxy balancer://couchlb>
BalancerMember http://192.168.1.11:5984
BalancerMember http://192.168.1.12:5984
</Proxy>
ProxyPass / balancer://couchlb
ProxyPassReverse / balancer://couchlb
DocumentRoot /usr/share/chef-server/public
LogLevel info
ErrorLog /var/log/chef/chef_couchdb_apache2-error.log
CustomLog /var/log/chef/chef_couchdb_apache2-access.log combined
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://couchlb%{REQUEST_URI} [P,QSA,L]
</VirtualHost>
EOF

Stop Couchdb on Chef-Server

*This will stop the continuous replication to couchdb01/couchdb02

root@chefserver:~# /etc/init.d/couchdb stop

Start Apache load balancer on Chef-Server

root@chefserver:~# a2ensite chef_couchdb_loadbalancer
root@chefserver:~# /etc/init.d/apache2 restart

Test your couchdb balancer:

http:://192.168.1.10:5984/_utils

You probably also want to edit your init scripts on couchdb01/02 to automatically restart the continuous replication upon start or restart
The replication does not persist after you stop a couchdb instance unless you explicitly issue the command again