Asterisk, and other worldly endeavours.

A blog by Leif Madsen

Archive for the ‘Programming’ Category

Configuring powerline to show working Git branch

So the documentation for Powerline kind of sucks. I followed this pretty good article on getting started with it. First thing I noticed however is that the if statement on the article doesn’t work if you don’t have powerline installed (which kind of defeats the purpose of having the if statement there at all).

# if powerline is installed, then use it
command -v powerline-daemon &>/dev/null
if [ $? -eq 0 ]; then
powerline-daemon -q
POWERLINE_BASH_CONTINUATION=1
POWERLINE_BASH_SELECT=1
. /usr/share/powerline/bash/powerline.sh
fi

Next up is the configuration. I primarily use my bash prompt as a way to indicate which branch I’m working in within a Git repository. You need to point at the default_leftonly theme which is pretty easy to find when you web search for it. The issue is everything seems to just point you at the powerline docs, which aren’t the most clear.

First, start by creating a local configuration directory that will override the configuration for powerline for your user.

$ mkdir -p ~/.config/powerline

Then the next thing is to copy over the config.json from the main powerline configuration directory where you can find the available color schemes and other shell, i3, vim, etc themes.

(Again, the documentation kind of sucks on where the root of these configurations live…)

On my Fedora 22 system they live in /etc/xdg/powerline/. I then copy the config.json from that directory to ~/.config/powerline

To get the Git branch stuff going, I modified the configuration file in the following way:

--- /etc/xdg/powerline/config.json 2015-02-18 18:56:51.000000000 -0500
+++ /home/lmadsen/.config/powerline/config.json 2015-09-09 17:11:43.937522571 -0400
@@ -18,7 +18,7 @@
},
"shell": {
"colorscheme": "default",
- "theme": "default",
+ "theme": "default_leftonly",
"local_themes": {
"continuation": "continuation",
"select": "select"

To make it active you can run powerline-config --reload. If you have any errors in your configuration (I actually ran into this when playing with the colorscheme setting and used “solorized” instead of “solarized”), you can check it with powerline-lint.

Advertisements

Written by Leif Madsen

2015/09/09 at 4:20 pm

bash creating files named ‘1’ everywhere!

So I ran into something kind of stupid today 🙂 Adding a little note for anyone who might run into a similar instance.

I have some ssh-add stuff that gets run in my .bashrc file, but when I was outputting it, I was doing:

ssh-add ~/.ssh/some_key > /dev/null 2&>1

Note the 2&>1 at the end. That means to redirect output to a file named 1. You need to flip the &> into >&, so the fixed version looks like:

ssh-add ~/.ssh/some_key > /dev/null 2>&1

Written by Leif Madsen

2012/07/19 at 10:03 am

Posted in Musings, Programming

Tagged with , , ,

Converting multiple exten => lines to using same => in Asterisk dialplan

Last week I wanted to start changing some 1.4 based Asterisk dialplan to a 1.8 based Asterisk system, and in that process wanted to convert lines like:

exten => _NXXNXXXXXX,1,NoOp()
exten => _NXXNXXXXXX,2,GotoIf($[...]?reject,1)
exten => _NXXNXXXXXX,3,Dial(SIP/foo/${EXTEN})
...

into using the same => prefix:

exten => _NXXNXXXXXX,1,NoOp()
 same => n,GotoIf($[...]?reject,1)
 same => n,Dial(SIP/foo/${EXTEN})

In order to do that, Mike King helped me out with the following regular expressing which I used in vim:

%s/exten\s*=>\s*[^,]\+,\s*[n2-9]/ same => n/g

Written by Leif Madsen

2012/01/16 at 8:28 am

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: http://opalsoft.net/qos/DS.htm

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 172.16.0.228/32 flowid 1:21

iptables -t mangle -A OUTPUT --dest 172.16.0.228 -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

Return just PID of script with ‘ps’ and ‘awk’

Today I ran into an issue where I am running a python script that I needed to get the process ID (PID) of, but that the process was being output with a space between ‘python’ and the actual script name (in this case, jiraircbot.py).

I’m sure it’s totally overkill and there is a much easier way I didn’t find to do this, but after some scouring of The Google, I found something that works! (The purpose of this was to kill off a rogue script process each night so I could restart it.)

Here is what the output looks like with just ps aux | grep python

# ps aux | grep python
root      1120  0.0  0.2  50176  4380 ?        Sl   Aug04  24:52 /usr/bin/python /usr/bin/fail2ban-server -b -s /var/run/fail2ban/fail2ban.sock
root     18182  2.2  1.5  35328 32148 pts/0    S    08:21   0:11 python jiraircbot.py
root     18219  0.0  0.0   3328   804 pts/0    S+   08:29   0:00 grep python

A little bit more data than I wanted, plus of course ‘grep python’ is always going to be returned if I just use grep straight up. Putting many pieces together from a few websites, this is what I came up with to just return the PID of the jiraircbot.py script:

ps -eo pid,command | grep "jiraircbot.py" | grep -v grep | awk '{print $1}'

What I’m doing, is controlling what is returned, so in this case have ps just return the pid and command fields. Run that through grep to just get the script I wanted, pipe that back through grep to remove the line including grep python and then pipe that through awk to just return the first field (which would be the pid of the process I wanted).

All in all, a nice hack 🙂

Written by Leif Madsen

2011/09/15 at 7:34 am

Posted in Being Productive, Programming

Tagged with , , , , ,

Set() and Goto() on same line

(Thanks to Jared Smith for answering my question in IRC which is the inspiration for this post.)

Typically when I write dialplan, primarily in the case where I’m using a pattern match, I’ll save the dialed extension to a channel variable using Set(), then do a Goto() where the call logic is handled. The Set() is so that I don’t lose the value of ${EXTEN} throughout the dialplan process, especially if I'm using other mechanics such as GoSub() and others.

I’ve been doing this on two or three lines like this (usually three because I like using a NoOp() or Verbose() for the first priority):

exten => _NXXNXXXXXX,1,NoOp()
   same => n,Set(DialedExtension=${EXTEN})
   same => n,Goto(CallHandler,1)

This is kind of annoying for each pattern match, especially if you’re going to do multiple. Here is a legitimate example of the CallHandler extension:

exten => _NXXNXXXXXX,1,NoOp()
   same => n,Set(DialedExtension=${EXTEN})
   same => n,Goto(CallHandler,1)

exten => _1NXXNXXXXXX,1,NoOp()
   same => n,Set(DialedExtension=${EXTEN})
   same => n,Goto(CallHandler,1)

exten => _NXXXXXX,1,NoOp()
   same => n,Set(DialedExtension=${EXTEN})
   same => n,Goto(CallHandler,1)

exten => CallHandler,1,NoOp()
   same => n,Dial(${GLOBAL(PSTN_CONNECTION)}/${DialedExtension},30)
   same => n,Hangup()

It’s a bit annoying having to either type out the same type of logic multiple times, even if it’s only 2-3 lines (even if you just copy and paste the same => lines it’s a bit better, but still not ideal). So here’s a solution to the same problem of multiple pattern matches and doing a Goto() our CallHandler extension.

exten => _NXXNXXXXXX,1,GotoIf($[${EXISTS(${SET(DialedExtension=${EXTEN})})}]?CallHandler,1:i,1)
exten => _1NXXNXXXXXX,1,GotoIf($[${EXISTS(${SET(DialedExtension=${EXTEN})})}]?CallHandler,1:i,1)
exten => _NXXXXXX,1,GotoIf($[${EXISTS(${SET(DialedExtension=${EXTEN})})}]?CallHandler,1:i,1)

exten => CallHandler,1,NoOp()
   same => n,Dial(${GLOBAL(PSTN_CONNECTION)}/${DialedExtension},30)
   same => n,Hangup()

exten => i,1,Congestion()

While both ways are perfectly reasonable (and some may argue the more verbose method is easier to read), I like embedding dialplan into a single line when I can as I find it easier to maintain. I’m also pretty good at knowing how many brackets to end with when nesting functions, but not everyone is comfortable doing that; in those cases you should probably break it out to multiple lines in order to save debugging time. Both methods are perfectly valid, so enjoy using whichever you prefer!

Written by Leif Madsen

2011/08/12 at 9:14 pm

Posted in Asterisk, Programming

Tagged with , ,

Connecting two conferences on initial join (with cleanup)

Update 2011/12/15: Updated the code to deal with a couple of people joining at about the same time by using GROUP() and GROUP_COUNT(). Additionally updated the ‘h’ extension which was missing some code

For the last week or so at work, people have been saying, “Hey, I can’t join the conference call this morning because I’m driving but I can’t call into the conference room on that server”. There are really a couple solutions to the problem, 1) everyone should use the conference room that is accessible via the PSTN, 2) get the IT staff to allow PSTN access to the internal conference room.

Those would be reasonable solutions, but who wants to be reasonable?! Terry Wilson suggested that we just keep a persistent connection between the two PBXs so that conferences could be joined. (I also earlier suggested that someone could just bridge the conference rooms together from their phone, but that required someone to remember to do that.) So instead of keeping the conferences connected indefinitely, I thought of a way to only connect them when the conference started, and then to kill it when the last person left.

Below you will see the dialplan I wrote that sets up the call between the conference rooms, then tears them down when the last person leaves. (In case you care, we’re connecting a MeetMe() room on a Switchvox server with the ConfBridge() application running on an Asterisk 10 based box — we use ConfBridge() to permit high quality audio and video conferencing during the daily stand up calls.)

[IncomingCalls]
exten => 500004,1,Verbose(2,${CALLERID(all)} is looking for a conference!)
   same => n,Playback(silence/1)
   same => n,Read(ConferenceRoom,conf-getconfno&beep)
   same => n,GotoIf($[${DIALPLAN_EXISTS(ConferenceRooms,${ConferenceRoom},1)}]?${ConferenceRoom},1:no_conf_room,1)
   same => n,Hangup()

include => ConferenceRooms

[ConferenceRooms]
exten => 12345,1,Answer()
   same => n,Verbose(2,${CALLERID(all)} is joining the wideband public conference room with ${CONFBRIDGE_INFO(paries,12345)} people)
   same => n,Set(GROUP(conference)=12345)
   same => n,ExecIf($[0${CONFBRIDGE_INFO(parties,12345)} < 1 & ${GROUP_COUNT(12345@conference)} <= 1]?Originate(Local/bridge_conference@ConferenceRooms,app,ConfBridge,12345))
   same => n,ConfBridge(12345)
   same => n,Hangup()

exten => bridge_conference,1,NoOp()
   same => n,Dial(SIP/7070@remote-server.tld,,D(wwww12345#))

exten => no_conf_room,1,Verbose(2,${CALLERID(all)} attempted to join an non-existant conference room)
   same => n,Playback(conf-invalid)
   same => n,Goto(500004,1)

exten => h,1,NoOp()
   same => n,ExecIf($[0${CONFBRIDGE_INFO(parties,11111)} <= 1]?SoftHangup(SIP/remote-server.tld,a))

Written by Leif Madsen

2011/08/11 at 10:48 am