Installing and migrating Ubiquity Unifi Controller software

I recently upgraded and expanded the wireless network at the office. We replaced our outdated and failing Linksys WRT54G routers with a set of Ubiquiti Unifi UAP-AC-LITE access points. The process of upgrading the network has been one of the more enjoyable tasks I have been assigned recently and the new wireless system works amazingly well.

This guide outlines installing the Unifi Controller software on an Ubuntu 14.04 server for configuring and managing the access points as well as migration from one controller to another.

Continue reading

Using cron to alert to known error conditions in log file

Recently I’ve been having issues with a VirtualBox machine crashing at random. The only common thread is a line of log file, and so far, google has not been helpful in determining the root cause. This machine is important enough that I need to know when it crashes, but not important enough to actually take the time to fix properly, so I researched and created a command to toss into cron to check the log file for the error line and email me when it finds it.

The command itself is simple. Search the log file with grep, if the search generated results send an email. I tried several iterations of this before finding one that did not email when the search was empty and also did not generate silent errors when empty as well. I run this via cron at 5 minute intervals

To use this command on ubuntu 14.04 you will need to install mailutils and moreutils

Software and versions used or mentioned:

Forum post with grep | mailx solution
ServerFault post with ifne solution

CakePHP 2.x routing

One of the larger issues I’ve had to deal with after being rehired is that the commissioning system we created had stopped producing reports, you could load the page, but no data would populate. These reports are populated via ajax, so I checked the request and found the error “No data found”. Several hours of digging and google slowly uncovered what was happening behind the scenes.

The root cause ended up being the url of the ajax request to pull the data. There were colons in the url. They were already encoded, but once you removed the time section of the datetime string, the reports worked again. These reports have remained unchanged since they were first developed over a year ago. The issue lay in the core of CakePHP. In particular the way the routing for requests had changed. We had been using 2.1 before and are now using 2.7. The two routing classes simply decode the url in different places, and the new one does it before the elements are turned into arguments passed to the controller.

I ended up coming up with two fixes. The first was to simply rename the old CakeRoute and use it as a custom routing class. This worked, but I didn’t test it heavily so there may have been issues. In addition, I was unable to find a method to restrict the custom routing class to only the controllers that needed it. The second method was to simply write a router connection in Config/routes.php where I defined the argument elements. This required a call for each controller action I wanted to fix and would end up being time intensive if you needed to manage a large number of routes, I only had four. You can see my routing code below.

Software and versions used or mentioned:
CakePHP 2.1 & 2.7

CakePHP 2.x Routing Documentation
CakePHP GitHub

PostgreSQL casting of ints to boolean fields

Recently I have been working with SQLite files part of a stand-alone application my company uses. We are getting ready to move the functionality from the stand-alone app to our web system. The app was designed with this eventual move in mind and it’s database file had been designed in such a way that we could simply do an export/import to move the data.

We used DB Browser for SQLite to export the database to a sql query we could import into our postgres database. There were some simple issues we needed to fix first (int(11) to int, tinyint(4) to boolean, etc). A simple find and replace for the file fixed those. But one issue we couldn’t fix was that PostgreSQL wouldn’t cast 0 and 1 to the boolean type. Due to the amount of data, a manual fix was impossible and we couldn’t think of a scripted way that wouldn’t cause unintended side effects. I googled the issue and there were some solutions, but it was an answer on a StackExchange question that had the fix (With a giant warning). This was an old answer and it was unclear what version of postgres the asker was using, so we tried it and it worked for us on Postgres 9.3.

Start by running the following:

Then we can run the offending SQL query. Of course we wouldn’t want to keep it like this for production, so we can reverse it with the following:

This is interesting, but I wanted to know more, all the query does is change a single field between ‘e’ and ‘a’, why does this work?

First off, pg_cast is a table that stores type conversion information, and it has a documentation page. We are changing the castcontext field of this table from ‘e’ to ‘a’ and back. Per the documentation: “e means only as an explicit cast (using CAST or :: syntax). a means implicitly in assignment to a target column” So we are simply removing the need for explicit casting.

If we do a SELECT on pg_cast and see the rows the query affects, we find it only changes a single row. Looking up the oids of the cast source and target shows that it is the cast from int4 (an alias of int) to bool. Since we aren’t changing the function used to do the casting, Postgres is obviously capable of the cast already, we just needed to give it a poke.

Software and versions used or mentioned:
PostgreSQL 9.3
DB Browser for SQLite

StackExchange question
PostgreSQL pg_cast documentation

A rehiring for me

Last year I got laid off from my development job. I then spent 10 months being unemployed and trying to find a new job. I don’t recommend being unemployed, particularly in Florida.

About a month ago, I was contacted by someone from my ex-job. He was looking for a small program to calculate the price of a product line. Normally the price was calculated by hand from the manufacturer’s book. I sat down with VS2013 and SQLite and got to work. Two weeks later I was demonstrating the small utility to a small gathering that happened to include the owner of the company. The following Monday I got a call to come in and I was rehired to my old job.

It’s nice jumping into a job where you are already familiar and knowledgeable with the company and peers. However, a lot of tools and data were lost when I left. It’s been frustrating finding and recovering systems and files from the various servers and hard drives. In addition the new mix of windows and linux development is stretching the very limited resources thin. It’s already taken three days to install and configure one development system.

I haven’t been updating this much since my source of problems to overcome was gone, but my current plan is to finish a few drafts I was working on before my period of unemployment and get them out. By then, I’m sure that I’ll have new things to write about.