Asterisk, and other worldly endeavours.

A blog by Leif Madsen

Archive for the ‘Useful Tools’ Category

Assign unique hostname to dhcp client with dnsmasq

Today I’ve been getting our lab environment setup with vagrant to auto-provision our lab servers with chef server in order to allow the development team to quickly and easily turn up and tear down web application servers.

Because when the server gets spun up with vagrant, it registers itself as a new node to the chef server using its hostname. Since using localhost for every node pretty much makes the chef server useless for more than 1 virtual machine at a time, I needed to figure out how to get dnsmasq to assign a unique hostname based on the IP address being provided by dnsmasq to the dhcp client.

I had seen a similar thing done with Amazon EC2 instances that when they turn up, they gets a hostname that looks similar to the private IP address it has been assigned. For example, if the private IP address assigned to the server was it would get a hostname like ip-192-168-12-14. I wanted to do a similar thing with our server.

After a little bit of Googling and reading the dnsmasq configuration file, it donned on me how simple this really was. You simply need to define the hostnames that the dnsmasq server could assign to a server, list those in the /etc/hosts file on the dnsmasq server, and then define the hostname you wanted to provide to the server. I didn’t want to use the MAC address of the servers (a la dhcp-host option) since the MAC address will be dynamic each time I spin up a virtual machine.

So in my dnsmasq.conf file I might have something defined like



So in my /etc/hosts file I’d just place the following to assign those unique hostnames:    ip-90-100-1-120    ip-90-100-1-121    ip-90-100-1-122    ip-90-100-1-123    ip-90-100-1-124

Written by Leif Madsen

2012/07/23 at 2:14 pm

rpmlint non-utf8-spec-file error

I’ve been doing a bunch of work with RPMs lately, and while running rpmlint against a spec file I was modifying, I received this error:

myfile.spec: E: non-utf8-spec-file myfile.spec

After Googling, I ran into a way of finding the non-compliant characters.

$ iconv -f ISO-8859-8 -t UTF-8 myfile.spec > converted.spec
$ diff -u myfile.spec converted.spec

(Answer thanks to Dominique Leuenberger @

Written by Leif Madsen

2012/02/23 at 1:43 pm

Posted in Useful Tools

Tagged with , , , ,

.bashrc trick for git repo and branch information

The other day I was talking to my friend Russell Bryant who pointed me to some .bashrc magic that would show me which branch I was currently working with inside a git repo on my system. I found it incredibly handy and have modified the ANSI colour coding slightly.

export PS1='[\u@\h \[33[0;36m\]\W$(__git_ps1 "\[33[0m\]\[33[0;33m\](%s)")\[33[0m\]]\$ '

On Fedora Russell mentioned that you need the bash-completion installed. We’re unsure if you need anything on other distributions.

Edit: January 6, 2012
As I’m using my laptop today, I modified the .bashrc file on Ubuntu 10.04, and here is the PS1 code I came up with. It’s nearly the same, but I’m using bold today instead of the unbolded colours of lore.

PS1='${debian_chroot:+($debian_chroot)}\[\033[28;01m\]\u@\h\[\033[00m\]:\[\033[1;36m\]\W$(__git_ps1 "\[\033[00m\]\[\033[1;33m\](%s)")\[\033[00m\]\$ '

Written by Leif Madsen

2011/12/22 at 9:39 am

Posted in Technology, Useful Tools

Tagged with , , , , , ,

Relaying SMTP via Gmail (or Google Apps) Using Postfix

Today I had the need to start relaying mail through my Google Apps account since Super-Evil-Bastard-ITSPRogers blocks sending email (it’s probably a good thing, however it’s quite annoying when running some services from home).

Found this article while Googling, and it worked great first try. I like when things are this easy.

Written by Leif Madsen

2011/11/22 at 5:17 pm

Controlling outbound bitrate using tc

Today I was using the VMware vCenter Converter application to build a VM from a physical machine so that I could replace Ubuntu 10.04.3 LTS with VMware ESXi (and move the functionality that the server is performing now to a VM instead of it being the base OS).

Because my server is colocated in a friends rack, and the bandwidth is shared, I needed to limit the rate at which the data was being sent from the colocated server to the virtual machine server. I needed to do this so he didn’t get pages, and so that my local connection would remain viable for VoIP communication.

After scouring Google, I found this page:

I looked at the HTB queuing section, and came up with a simple rate limiter for my outbound data to a specific IP. The example he shows is more complex, but it gave me enough to make it work. Here is what I entered at the console:

tc qdisc del dev eth0 root  # clear existing rules
tc qdisc add dev eth0 root handle 1:0 htb
tc class add dev eth0 parent 1:0 classid 1:1 htb rate 2048kbit
tc class add dev eth0 parent 1:1 classid 1:2 htb rate 1228kbit ceil 2048kbit
tc class add dev eth0 parent 1:2 classid 1:21 htb rate 1228kbit ceil 2048kbit
tc qdisc add dev eth0 parent 1:21 handle 210: pfifo limit 10
tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip dst flowid 1:21

iptables -t mangle -A OUTPUT --dest -p tcp -j MARK --set-mark 21

I’m sure I could have made that a bit more efficient on lines 4 and 5, but not knowing a ton about tc and the fact it worked, made me happy enough 🙂

Written by Leif Madsen

2011/11/02 at 11:08 am

Initial impressions of qemu-kvm (virtualization server)

The qemu-kvm ( package on Ubuntu 10.10 allows you to create virtual machines much like VMware, Xen, etc.

My initial impressions are generally pretty positive. I like that it lets you install multiple operating systems (including MS Windows, which I haven’t tried yet), and doesn’t use a web interface like VMware Server 2 (which I’ve found to be terribly crash prone, requiring a restart of the web interface at the least, and sometime the entire server needs to be restarted, often abruptly with the kill application). My favourite part is the libvirt-manager that lets you manage the system and install virtual machines remotely over SSH using VNC (or at least something similar to it).

The one problem I had initially was installing CentOS 5.5. It was terribly slow, and when I started the virtual machine, I coudn’t get it past GRUB. I thought perhaps it was just a problem with running CentOS VMs on an Ubuntu host machine, but then I had the same problem with an Ubuntu installation (which took at least 3-4 times as long to install as CentOS for some reason).

I got looking around and found people with similar issues as me, but they all basically just outlined reinstalling GRUB via a rescue disk. I tried this which got me just a little bit further, but still no GRUB menu, or system booting.

Then I found a post indicating that restarting the KVM service caused things to work, which I tried doing, but nothing changed. So as a last ditch effort I tried rebooting the service, which I didn’t expect to actually fix anything, but oddly enough worked. The existing VMs I installed started up fine, and the new installation I tried went significantly faster.

I haven’t had much of a chance to try more than what I’ve described, but thus far I like KVM a lot more than VMware. Hopefully I keep enjoying it as I go forward now that I’ve gotten VMs to boot 🙂

Written by Leif Madsen

2011/02/08 at 8:18 pm

Scheduling automated calls between two participants with res_calendar

Here is a little dialplan snippet I wrote this morning for the next edition of the Asterisk book. While I’m not going to delve into all the aspects of setting up res_calendar like we do in the book, I thought for those of you who might already have this working might enjoy it.

(The calendaring modules are available in Asterisk 1.8, which is currently in release candidate status. Check out for the current version.)

I started with this little bit of dialplan that gets triggered when a call is answered from the calendaring module:

exten => start,1,Verbose(2,Triggering meeting setup for two participants)
   same => n,Set(DeviceToDial=${FILTER(0-9A-Za-z,${CALENDAR_EVENT(location)})})
   same => n,Dial(SIP/${DeviceToDial},30)
   same => n,Hangup()

The location field in my calendar event (which in this case is labeled as Destination in my Google Calendar) contains the string 0000FFFF0002 which is the device identifier in my example.

Once you get that working, the cool magic happens below. In the following example, a call is placed from the calendaring module when a meeting needs to take place between two participants. The first part of the dialplan allows the first person called to accept or reject the meeting, and if accepted, to record a message for the other party. Once that recording is saved, the dialplan will go ahead and trigger a call to the other meeting participant.

When that meeting participant answers the call, a Macro() is employed to allow them to listen to the recorded message left by the first party, (i.e. “Hey Jim, this is Leif. We have a meeting scheduled right now.”). That person is then presented the same option to accept or reject the call by pressing 1 or 2.

Of course the dialplan could even by further expanded to play back messages when the calls were rejected, the option for the called party to leave a return message of why they are rejecting the call, and maybe even the ability to post-pone the call for a few minutes. All it takes is some clever dialplan!

exten => start,1,Verbose(2,Triggering meeting setup for two participants)
same => n,Read(CheckMeetingAcceptance,to-confirm-wakeup&press-1&otherwise&press-2,,1)
same => n,GotoIf($["${CheckMeetingAcceptance}" != "1"]?hangup,1)

same => n,Playback(silence/1&pls-rcrd-name-at-tone&and-prs-pound-whn-finished)
same => n,Set(__RandomNumber=${RAND()})
same => n,Record(/tmp/meeting-invite-${RandomNumber}.ulaw)

same => n,Set(DeviceToDial=${FILTER(0-9A-Za-z,${CALENDAR_EVENT(location)})})
same => n,Dial(SIP/${DeviceToDial},30,M(CheckConfirm))
same => n,Hangup()

exten => hangup,1,Verbose(2,Call was rejected)
same => n,Playback(vm-goodbye)
same => n,Hangup()

exten => s,1,Verbose(2,Allowing called party to accept or reject)
same => n,Playback(/tmp/meeting-invite-${RandomNumber})
same => n,Read(CheckMeetingAcceptance,to-confirm-wakeup&press-1&otherwise&press-2,,1)
same => n,GotoIf($["${CheckMeetingAcceptance}" != "1"]?hangup,1)

exten => hangup,1,Verbose(2,Call was rejected by called party)
same => n,Playback(vm-goodbye)
same => n,Hangup()

Written by Leif Madsen

2010/09/29 at 9:25 am