John T Dyer

Director of Awesome

Ohai, Vagrant and Eth1… Making Them Work in Harmony

Unfortunately Vagrant deployments always have the NAT adapter on eth0, which can cause headaches at times, especially when doing a multiVM deployment! Most of the time you end up having to modify the recipe to make things work. In my humble opinion these changes kind of defeat the purpose of testing in Vagrant to begin with. So what to do ? We’ll you can use an Ohai plugin and override the node.ipaddress value ! So what we’ll do is make eth1 pretend to be eth0 !

Now since I want to make sure my cookbooks are the same in development as production I will want to make sure we don’t use this plugin in production. That being the case we’ll go ahead and add some guards to ensure this is only loaded when we are on a VirtualBox VM. Just for good measure we’ll also check for the vagrant user, and make sure that there is in fact an eth1 adapter. I feel this is enough of a safe guard to ensure we only apply this plugin if running under Vagrant, and only when needed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
provide "ipaddress"
require_plugin "#{os}::network"
require_plugin "#{os}::virtualization"
require_plugin "passwd"

if virtualization["system"] == "vbox"
  if etc["passwd"].any? { |k,v| k == "vagrant"}
    if network["interfaces"]["eth1"]
      network["interfaces"]["eth1"]["addresses"].each do |ip, params|
        if params['family'] == ('inet')
          ipaddress ip
        end
      end
    end
  end
end

We can now distribute this w/ the Ohai Plugin Cookbook and not have to make any changes regardless of the environment ( Production / Development ).

Creating a Release RPM

First setup your rpm workspace

1
2
rpmdev-setuptree
cd ~/rpmbuild/SOURCES

Then copy your repo files into this dir ( RPM-GPG-KEY-voxeo-labs voxeo-labs.repo)

Next you want to go ahead and create your spec file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#
# spec file for VoxeoLabs Yum Repo
#
Summary: Voxeolabs repository configuration
Name: voxeolabs
Version:        0.0.1
Release:        1%{?dist}
License:        GPLv3
Group: System Environment/Base

URL:            http://yum.voxeolabs.net/
Source0:        http://yum.voxeolabs.net.s3.amazonaws.com/pub/voxeolabs-0.0.1.el.tgz

BuildRoot: %{_tmpdir}/%{name}-%{version}-%{release}

Vendor: Voxeo Labs
Packager: John Dyer <jdyer@voxeo.com>

%description
This package contains the Voxeo Labs yum repo.  It includes the  GPG key as well as configuration for yum.

%prep
%setup -q

%build

%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/yum.repos.d/
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/pki/rpm-gpg/
cp -p voxeo-labs.repo $RPM_BUILD_ROOT%{_sysconfdir}/yum.repos.d/
cp -p RPM-GPG-KEY-voxeo-labs $RPM_BUILD_ROOT%{_sysconfdir}/pki/rpm-gpg/

%clean
rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root,-)
/etc/yum.repos.d/voxeo-labs.repo
/etc/pki/rpm-gpg/RPM-GPG-KEY-voxeo-labs

%post
yum clean all

%changelog
* Sun Aug 27 2012 John Dyer <jdyer@voxeo.com> 0.0.1
- Initial release

Now because we use Amazon AMI’s on AWS, which is el6, and CentOS5 a few other places, I want the post install step to fix the repo to point to the right place on our YUM server. We will do this by checking a few files to determin our version of CentOS and then update the repo file. We do this because Amazon Linux, which is pretty much el6, returns ‘amzn’ for $releasever, which can be problematic.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
%post

# Retrieve Platform and Platform Version

if [ -f "/etc/redhat-release" ];
then
  platform=$(sed 's/^\(.\+\) release.*/\1/' /etc/redhat-release | tr '[A-Z]' '[a-z]')
  platform_version=$(sed 's/^.\+ release \([.0-9]\+\).*/\1/' /etc/redhat-release)

  # If /etc/redhat-release exists, we act like RHEL by default
  if [ "$platform" = "fedora" ];
  then
    # Change platform version for use below.
    platform_version="6.0"
  fi
  platform="el"
elif [ -f "/etc/system-release" ];
then
  platform=$(sed 's/^\(.\+\) release.\+/\1/' /etc/system-release | tr '[A-Z]' '[a-z]')
  platform_version=$(sed 's/^.\+ release \([.0-9]\+\).*/\1/' /etc/system-release | tr '[A-Z]' '[a-z]')
  # amazon is built off of fedora, so act like RHEL
  if [ "$platform" = "amazon linux ami" ];
  then
    platform="el"
    platform_version="6.0"
  fi
fi

sed -i -e "s/\$releasever/`echo $platform_version | cut -d. -f1`/g" /etc/yum.repos.d/voxeo-labs.repo

In the end your spec script should look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#
# spec file for VoxeoLabs Yum Repo
#
Summary: Voxeolabs repository configuration
Name: voxeolabs
Version:        0.0.1
Release:        1%{?dist}
License:        GPLv3
Group: System Environment/Base

URL:            http://yum.voxeolabs.net/
Source0:        http://yum.voxeolabs.net.s3.amazonaws.com/pub/voxeolabs-0.0.1.el.tgz

BuildRoot: %{_tmpdir}/%{name}-%{version}-%{release}

Vendor: Voxeo Labs
Packager: John Dyer <jdyer@voxeo.com>

%description
This package contains the Voxeo Labs yum repo.  It includes the  GPG key as well as configuration for yum.

%prep
%setup -q

%build

%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/yum.repos.d/
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/pki/rpm-gpg/
cp -p voxeo-labs.repo $RPM_BUILD_ROOT%{_sysconfdir}/yum.repos.d/
cp -p RPM-GPG-KEY-voxeo-labs $RPM_BUILD_ROOT%{_sysconfdir}/pki/rpm-gpg/

%clean
rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root,-)
/etc/yum.repos.d/voxeo-labs.repo
/etc/pki/rpm-gpg/RPM-GPG-KEY-voxeo-labs

%post

%post

# Retrieve Platform and Platform Version

if [ -f "/etc/redhat-release" ];
then
  platform=$(sed 's/^\(.\+\) release.*/\1/' /etc/redhat-release | tr '[A-Z]' '[a-z]')
  platform_version=$(sed 's/^.\+ release \([.0-9]\+\).*/\1/' /etc/redhat-release)

  # If /etc/redhat-release exists, we act like RHEL by default
  if [ "$platform" = "fedora" ];
  then
    # Change platform version for use below.
    platform_version="6.0"
  fi
  platform="el"
elif [ -f "/etc/system-release" ];
then
  platform=$(sed 's/^\(.\+\) release.\+/\1/' /etc/system-release | tr '[A-Z]' '[a-z]')
  platform_version=$(sed 's/^.\+ release \([.0-9]\+\).*/\1/' /etc/system-release | tr '[A-Z]' '[a-z]')
  # amazon is built off of fedora, so act like RHEL
  if [ "$platform" = "amazon linux ami" ];
  then
    platform="el"
    platform_version="6.0"
  fi
fi

sed -i -e "s/\$releasever/`echo $platform_version | cut -d. -f1`/g" /etc/yum.repos.d/voxeo-labs.repo
yum clean all

%changelog
* Sun Aug 27 2012 John Dyer <jdyer@voxeo.com> 0.0.1
- Initial release

Then you want to just run

1
rpmbuild -bb ruby19.spec

Using SOX to Batch Convert Audio Files

The Plain old telephone service (POTS) we are all used to is almost a hundred years old so when it comes to audio codecs you get pretty much the bottom of the barrel. When doing IVR you will want to make sure you convert all your media to the lowest common denominator, which is generally 8bit, 8Khz Mono. Doing this w/ SOX is pretty simple

1
2
3
4
for i in *.wav
do
 sox $i -r 8000 -U -b 8 new-files/$(basename $i)
done

Thats pretty much it ! If you are using OSX you can get SOX by installing Homebrew and running:

1
brew install sox

Hope that helps someone

-John

Using Nagios to Monitor Tropo

So I will start by saying that Tropo maintains a very redundant, and fault tollerent network, however we do understand that people still need to do their due dilligance and implement monitoring just to be safe. So yesterday we had a developer that wanted do just this, they wanted to monitor Tropo’s SBC’s to ensure they were responding to requests as expected. The only problem here is that Tropo’s SBC’s don’t implelment OPTIONS and all the plugins for Nagios seem to use OPTIONS in their tests, however one seems to allow you to specify the response code for a passing test. This plugin is the NagiosSIP plugin, and via the -c ( SIP_CODE) flag we can set a 501 ( SIP/501 Not Implemented) as a passing test, since a 501 would signify a responding SBC. Check out below for an example of just what I mean:

1
2
10:51:28 jdyer@aleph.local ./nagios_sip_plugin.rb -s sip.tropo.com -c 501
OK:status code = 501

We can also see the exit code is 0, which would be a pass

1
2
10:51:33 jdyer@aleph.local echo $?
0

Sure hope someone finds this helpful!

-John

Installing Asterisk 10.3 on OSX Lion

So I had a need to install Asterisk the other day on my laptop and doing the atypical:

1
2
3
./configure
make
make install

Gave me a whole bunch of suck

1
2
3
4
5
6
7
8
snmp/agent.c: In function ‘init_asterisk_mib’:
snmp/agent.c:835: error: ‘RONLY’ undeclared (first use in this function)
snmp/agent.c:835: error: (Each undeclared identifier is reported only once
snmp/agent.c:835: error: for each function it appears in.)
make[1]: *** [snmp/agent.o] Error 1
make[1]: *** Waiting for unfinished jobs....
   [LD] chan_unistim.o -> chan_unistim.so
make: *** [res] Error 2

Little bit of digging led to a bunch of solution thats didn’t seem to work, but after a little bit of trail and error I found a quick, and working solution, which I figured I would share

1
2
3
4
5
./configure --host=x86_64-darwin
make menuselect ( remove res_snmp under Resource Modules )
sudo make -j 4
sudo make install
sudo make samples

Worked for me, and I hope it helps someone else!

-John

API for AWS Pricing

Looking for an easy way to get AWS pricing programitcaially? Just use the following three URI’s to get a JSON feed of transfer costs, as well as Reserved and On-Demand instance pricing:

1
2
3
https://aws.amazon.com/ec2/pricing/pricing-on-demand-instances.json
https://aws.amazon.com/ec2/pricing/pricing-reserved-instances.json
https://aws.amazon.com/ec2/pricing/pricing-data-transfer.json

Enjoy

-John

TinyTDS & OSX 10.7

Very simple

1
2
3
brew install freetds
gem install tiny_tds
profit

Installing ELB Command Line Tools on OSX / Linux

The ELB command line tools are pretty nice, and they are actually required to get a lot of important information which is unfortunately missing from the AWS ELB UI. Installation is actually quite simple, first go ahead and download the zip from here, and then just go ahead and do the following:

1
2
3
4
wget http://ec2-downloads.s3.amazonaws.com/ElasticLoadBalancing.zip
unzip ElasticLoadBalancing.zip -d ~/bin
echo "EXPORT ~/bin/`ls ~/bin | grep Elastic`" >> ~/.bash_profile
source ~/.bash_profile

Then boom, magic

1
2
3
4
5
6
7
8
10:50:24 jdyer@aleph.local Downloads elb-describe-lbs -h                                                                                                                                                                    127 ↵

SYNOPSIS
   elb-describe-lbs
       [LoadBalancerNames [LoadBalancerNames ...] ]  [General Options]

DESCRIPTION
       Describes the state and properties of LoadBalancers

Hope that helps!

Print Letters Up to N in Ruby

Had a case the other day where I needed to create users accounts in a specific fashion. If I had less then 25 users I would use letters for the test accounts (eg: usera, userb, ect), if there were more then 25 I would use numbered accounts (eg: user1, user2, ect ) The problem was there could be any number of user accounts and I wanted to keep to this schema.

Unfortunately Enumerable wasn’t going to make this as easy as most things are in ruby, like this wasn’t going to work:

1
"a".upto(5)

However I figured I could just switch to their ascii equivalent and then this would be easy!

1
2
3
4
5
6
num_of_users = 25
if num_of_users <= 25
  (97..97+num_of_users).each{|e| puts e.chr}
else
  num_of_users.times{|e| puts e}
end

Worked like a charm!

Upgrade Chef Server to 0.10.8

Upgrading to Chef Server ( 0.10.8 ) is dead simple, takes probably 30 seconds.

1
2
3
for s in server server-webui solr expander; do sudo /etc/init.d/chef-${s} stop; done
sudo gem update chef chef-server --no-ri --no-rdoc
for s in server server-webui solr expander; do sudo /etc/init.d/chef-${s} start; done

If you want you can backup the server first using Seth’s backup script ( here ). Installing, and running it, is dead simple:

1
2
curl -O https://raw.github.com/jtimberman/knife-scripts/master/chef_server_backup.rb
knife exec chef_server_backup.rb

This will create a backup fo the server in your .chef dir. Enjoy