Tuesday, September 17, 2013

Setting Up RAID-1 on Linux Mint 15, Revisited using manual commands

So, after I ran the raider program a while back, I had to do some other things with my machine ~ and long story short, I had to run raider once again. Only this time, I didn't do it right (I used the machine for a full day after running the initial raider setup and before swapping the drives - meaning that when I finally got around to completing the "raider --run" step, things were out of sync and crapped out)...

Originally, I started with my /dev/sda having all my stuff on it and /dev/sdb being the blank drive I wanted to add as a new member of a RAID-1 array... but, instead, (thanks to my screw-up) I ended up with /dev/sdb getting my system (thanks to raider's first step) and /dev/sda getting completely erased. Not a complete disaster, since I still had all my stuff on at least one of the drives, but I didn't have the time to wait for two more rebuilds, nor the patience to swap drives and stuff. So, I decided to jump in and try to figure out mdadm, proper... at least this was a good introduction to a little bit of the utility.

Since my mdraid had already been created (again, thanks to raider), all I needed to do was manage the array. So, the first thing I wanted to do was copy sdb to sda. This turns out to be pretty easy:

  • First, copy the partition table from your source drive to the new RAID member drive:
    # sfdisk -d /dev/sdb | sfdisk /dev/sda
  • Then, add the erased disk to the raid array:
    • Add /boot partition
      # mdadm --manage /dev/md0 --add /dev/sda1
    • Add / partition
      # mdadm --manage /dev/md1 --add /dev/sda3
    • Add /home partition
      # mdadm --manage /dev/md2 --add /dev/sda4
At this point, I checked the array (# cat /proc/mdstat) and discovered, to my surprise, that the array was already rebuilding (i.e. copying stuff from my sdb to my sda)!

Mission accomplished: I can now continue using my machine while the array rebuilds in the background. Since that will take another day or so, I'll continue this if there are other issues.....

To be continued?!


Wednesday, September 11, 2013

Updating the "WP to Twitter" WordPress Plugin to Fix "Code 410" Errors

I found myself in the position of needing to update our "WordPress to Twitter" plugin (http://wordpress.org/plugins/wp-to-twitter/) from version 2.6.7 to 2.7.3, due to getting a constant "Code 410" error whenever we tried to do a post - apparently an issue with Twitter's 1.1 API update. Here's how I did it:

  1. Deactivated the old wp-to-twitter plugin, using the WordPress "Plugins" admin-console.
  2. Using a Linux terminal with direct server access, I scp'd the new version's ZIP file over and unzipped it into my /wp-content/plugins directory.
    • When prompted to overwrite files, I chose "A" for all.
  3. Went back to my plugins admin-console, refreshed the page and reactivated the plugin.
All settings (including my Twitter API keys/tokens/secrets, bit.ly, etc.) were miraculously still there, and the new version appears to be up and running. Quite a nice surprise, when it comes to managing WordPress!

Tuesday, September 10, 2013

Randomly Rotate Strings for Display on a WordPress Page Using PHP (Shortcode Exec)

I was asked by our marketing team if we could have our WordPress-based homepage randomly display one of several possible tag lines. Well, sure... with PHP it's dead simple. And if you have Shortcode Exec PHP installed in your WordPress site, it's actually even easy under WordPress.

Here's how I did our particular page. It will randomly choose a string from a PHP array, and present it in a clean looking, rounded-corner wrapper. If you use this, of course you may want to modify the strings and styles to suit your needs. Note, rounded corners aren't fully supported by most IE versions ~ I try not to waste time developing for IE, but if you have a solution, feel free to post it here.

Create a new Shortcode Exec PHP like so...
/* Rotate random hyperbole lines on the homepage */
$hyperboleStrings = array(
1  => "We have the best product",
2  => "Our solution solves problems",
3  => "Industry leading solutions"
);
$whichStringToShow = rand(1, sizeOf($hyperboleStrings));
echo $hyperboleStrings[$whichStringToShow];
Now all you have to do is save it and go to the page you want to add it to. In my case, I had to go to Appearance -> Editor -> header.php...
<div class="rounded_corners" id="hyperbole-line">
<?php echo do_shortcode("[homepage_hyperbole_rotator]"); ?>
</div>
And, here's my CSS...
.rounded_corners {
-moz-border-radius: 10px; /* firefox */
-webkit-border-radius: 10px; /* safari, chrome */
-khtml-border-radius: 10px; /* KDE HTML layout engines */
border-radius: 10px; /* css3 */
}
#hyperbole-line {
background-color: #20b0b0;
width: 85%;
padding: .25em;
text-align: center;
margin: 10px auto 10px auto;
color: #fff;
font-style: italic;
font-size: 1.75em;
padding: 0;
letter-spacing: 1px;
}

Monday, September 9, 2013

Can Philips Hue Lights be Controlled by Third-Party Controllers?

In developing applications with the Philips Hue lights, it's become painfully apparent that the "bridge" (the white circular control device that comes in Hue starter kits) is pretty inadequate. Philips has not been very developer-friendly to those of us with more advanced needs than a disco smartphone app.

The woefully inadequate bridge has rate limiting... it does stuff that you may not want it to, in ways that you may not desire... not to mention that you're pretty much stuck with their paltry API and its limited functionality, etc. Basically, it's like being stuck with an old un-rootable Android phone, when you could otherwise breathe new life into it (and have advanced capabilities) by flashing a custom ROM to it (Apple fans: substitute jail-breaking for this analogy).

So, I got to wondering: why couldn't the lights can be controlled without going through the Philips-supplied, Philips-controlled bridge? The bridge is just an IP-to-Zigbee gateway... in other words, it connects two separate networks: your IP network and the lights' wireless Zigbee network.

If there were some other third-party device that would do this -- one which would give you more direct control of the lights, then you could seemingly go completely around Philips' restrictive control, right? If my server could have more "direct" access to the Zigbee network, I think I could do some pretty slick things... right?

Enter, the Digi ConnectPort X2e.
I found this product via a co-worker's suggestion (he's had recent experience with Zigbee devices), and it's basically just a programmable IP-to-Zigbee gateway (probably just an embedded Linux SoC). Hmmmm.... now I just need to figure out how to develop it's Python-compatible programs on a Linux machine (they seem to only offer an IDE running under Windows or Mac).

So it begins, my venture deeper into advanced Philips Hue light development; and, moreover, further opening the door to the M2M world. More hopefully to come...

Friday, September 6, 2013

Setting Up RAID-1 on Linux Mint 15, Made Easy

Having come from the RHEL/CentOS world, it was a bit of a surprise to me when I installed Linux Mint 15, and noticed the lack of a software RAID setup step during the install process. But this can easily be done once installation is complete ("easy," relative to manually running mdadm, anyway).

Here's a handy little tool I found to ease the implementation of software RAID-1: raider (http://raider.sourceforge.net/).

By using this tool, I didn't lose any data or anything... just installed the OS and then ran raider after the fact. It really wasn't too painful (just takes some time and requires pulling cables a couple times). And, don't be put off by the low version number ~ it worked great for me, for this purpose.

My hardware consists of two hard drives, as follows:
(no LVM, no encryption - just plain, pure hardware devices)
/dev/sda  (2TB WD-black - Linux Mint 15 already installed)
/dev/sdb  (2TB WD-black - some previous file system I don't care about anymore)

If you follow the directions (including physically swapping the two hard drives' SATA cables and allowing them to rebuild), you'll get great results... at least I did.

  1. Download and then extract the package (I used version 0.13.2) anywhere (I used my ~/).
  2. CD into the raider directory and install:
    $ sudo ./install.sh
  3. Make sure you have the required packages installed (I only needed mdadm):
    $ sudo apt-get install mdadm parted sfdisk hdparm rsync bc wget
  4. Make sure you have at least one of the following installed (I already had mkinitramfs): dracut, mkinitcpio, mkinitramfs, mkinitrd, or genkernel
  5. Backup your stuff! (duh) ~ I didn't need to resort to it, but you never know.
  6. Reboot into single user mode:
    1. When booting, hold the shift key until you see the GRUB boot screen.
    2. Press "e" to edit the line, and append the word "single" (without quotes) at the end of the line (in my case, after the "ro quiet splash" part)
    3. Press "Ctrl" + "x" to execute the boot (it'll drop you into command line mode)
    4. Log in as root.
  7. Run the following command... raider will use the drive in the first physical slot (almost always sda) as the "source" drive and you will lose whatever is on the second drive (sdb). Be aware that this might take a long time ~ it took around 5 hours with my 2TB drive that had about 500GB of stuff on it.
    # raider -R1 sda sdb
    • Note: If your sdb had stuff on it before (especially RAID), you might get a message about needing to erase it. If you do, just run the command it says to run: raider --erase /dev/sdb
    • Note: If you get the "fatal error" about not being able to format a particular partition (in my case, it was the swap partition of the old disk), then you'll need to first do an fdisk on sdb, and delete all the partitions (just to be safe - you don't care about them anymore, anyway, right?). Be sure to reboot after you write the changes in fdisk. Then run the raider command again.
  8. Once that completes...
    1. Shutdown the machine
    2. Physically swap the two hard drives' data connectors with each other
    3. Boot back into single user mode (repeat step 6 above)
  9. Run the command:
    # raider --run
    • Essentially, we've now simulated a degraded array (sdb isn't complete, but we're booting from it as sda this time), and we're now going to rebuild it. Other than copying the sda's contents to sdb, the added bonus is that we're also testing the array's ability to rebuild here.
    • Note: this will take quite a long time... for my 2TB drives, it took about 8 hours!
  10. Once that completes... (at this point, you should now have two identical drives as members of a functional and working RAID-1 array)
    1. Shutdown the machine
    2. Physically swap back the two hard drives' data connectors with each other (the way they were originally)
    3. Boot back up as you normally do... you're all done!

Thursday, September 5, 2013

Exclude WordPress Recent Posts Having a Certain Category

Say you have a homepage that you list recent posts on, using the "Recent Posts" widget or something.

Also say that you want to exclude posts that have a certain category. In my case, I have regular blog posts, and I also have a category of blog posts for "Press Releases" that I have a separate section on my homepage for.

Well, I don't want duplicated post links on my homepage, now, do I?

So, here's the hack (I prefer to avoid the term "solution" when dealing with WordPress)...

In my theme's functions.php file (Appearance -> Editor -> Theme Functions), I added the following bit of code at the end (change the red text to the appropriate ID of the category you wish to exclude - you should be able to specify multiple categories by separating them with spaces e.g. '-1 -2 -3'):
function exclude_category($query)
  {
  if ( $query->is_home() )
    {
    $query->set('cat', '-TAG ID OF CATEGORY');
    }
  return $query;
  }
add_filter('pre_get_posts', 'exclude_category');
From what I'm able to gather, the function intercepts the standard procedure for getting posts, via the add_filter function. More of your typical WordPress voodoo black magic, if you ask me... building layers upon layers upon layers /smh.