Archive for the ‘HOW-TOs’ Category.

How to check RAID status on an Intel board

I don’t want to dwell on how many hours I just wasted trying to get the status of an embedded RAID controller on an Intel S3420GP board running openSUSE 11.3. The solution is to avoid the dizzying array of software that Intel offers on their website, and instead use dmraid.

My understanding of this is a little shaky, but first you need to know where the controller is mapped. After some poking around the system, I came across this:

# ls -1 /dev/mapper
control
ddf1_MegaSR___R1__0
ddf1_MegaSR___R1__0_part1
ddf1_MegaSR___R1__0_part2
ddf1_MegaSR___R1__0_part3

I know my array has three partitions so it seemed intuitive that the device was named ddf1_MegaSR___R1__0. I was then able to get the status with:

# dmraid -s ddf1_MegaSR___R1__0
*** Group superset .ddf1_disks
--> Active Subset
name   : ddf1_MegaSR___R1__0
size   : 623046656
stride : 128
type   : mirror
status : ok
subsets: 0
devs   : 2
spares : 0

Unbelievably simple after I had waded through failed attempts at using Intel’s RAID Web Console 2, Intel’s Extensible Firmware Interface (EFI), Intel’s Damn? Platform Control Command Line Interface (DPCCLI), Intel’s Active System Console (IASC), and who knows what else.

Linux had the answer the entire time in a scriptable format. I’d feel bad for all that time I spent, except I’m too excited about finally being able to add this controller to the cronjob that tells me how my RAID arrays are doing every morning.

How to combine/concatenate mp4 videos

In a project similar to the Blender Defender, I am using a Linksys WVC54GCA webcam to monitor my devious cats. The camera has built-in motion detection, and can automatically FTP video files of detected motion to a location of your choice. Unfortunately, the area I’m monitoring has a good deal of exposure to outside lighting, meaning that each day I get hundreds of little videos as light plays across the room.

While messing with the motion sensitivity settings is next on my list, my immediate reaction was to figure out a way to combine the videos. The WVC54GCA lets you use a few different formats, but I chose mp4 since that seemed like the most open format. Some Google searching told me that I needed to use ffmpeg to convert the mp4s to mpg format which is supposedly “concatenatable”.

So first I converted all my mp4s to mpgs (assuming they are stored in a directory called movie_dir):

find movie_dir -name "*.mp4" -exec ffmpeg -i {} -sameq {}.mpg \;

Many posts I found then said that all one needed to do was just cat the mpg files together and you’d end up with one long mpg. That sounded great, but in practice it produced an mpg that caused both QuickTime and VLC to either choke, skip past chunks of video, or otherwise be weird. Going back to the Internet, I found that the solution was to use ffmpeg again to produce a single video:

cat movie_dir/*.mpg | ffmpeg -f mpeg -i - -vcodec copy -acodec copy big_movie.mpg

And this I can enjoy 30 boring minutes of watching the light level change, waiting for that one moment when the cats try to sneak up on the couch. Now I know how a security guard feels.

Solving openSUSE 11.3 mail server problems

Rather than follow an upgrade path, I painstakingly migrated the mail server configuration from an openSUSE 11.0 server to a fresh install on an openSUSE 11.3 server. Here are the problems I ran into and how I solved them:

Problem: “Permission denied” when postfix/lmtp attempted to connect to /var/lib/imap/socket/lmtp

Solution: run vigr to add user postfix to the mail group.

Problem: imap[14973]: IOERROR: opening /var/lib/imap/user_deny.db: No such file or directory

Solution: it’s okay to ignore this.

Problem: imap[10976]: SQUAT failed to open index file
imap[10976]: SQUAT failed

Solution: you can either ignore this or build SQUAT indexes.

Problem: postfix/smtp[21515]: connect to localhost[::1]:10024: Connection refused
amavis[21058]: (21058-12) (!!)WARN: all primary virus scanners failed, considering backups

Solution: the Problems I found and fixed section of this Virus scanning post seemed to have the answer. All I needed to do was uncomment the ClamAV-clamd lines in /etc/amavisd.conf

How to recommend movies to friends on Netflix

Do you remember when Netflix used to have a Netflix Community feature where you could add friends and recommend movies to one another? I was just now about to make a recommendation when I realized I could no longer find that feature, nor a listing of my Netflix friends.

If you peruse this forum, then you’ll find that Netflix has removed all of their “community” features. A poster in that forum recommended calling Netflix customer service (1-866-716-0414) to request the return of this feature.

I really liked that feature so I gave them a call. The rep was very friendly and told me they removed the community stuff because less than 2% of their customers were using it. Unfortunately I can’t really argue against those numbers. Still, the rep was kind enough to pass on the “re-feature” request to their dev team. Who knows, maybe if they get enough calls then they will bring it back. Personally, I think if they worked a bit harder to promote the community (read: social networking) aspect of their site, then those features would see heavier usage.

The only problem is, what would Netflix gain? The best answer I could come up with is that as a business you would remain “hip to the times” and stay ahead of your competition. If a customer has a social network built up within Netflix, then they are much less likely to change services.

So anyway, I’ve been watching Dexter and it’s freaking awesome.

fdisk problems with large partitions

I recently upgraded my 3ware 9550SX-8LP RAID5 array from 250 GB drives to 1 TB drives. After the lengthy RAID initialization process, I tried to create a partition using fdisk. Unfortunately, fdisk seemed to only create a partition size of about 400 GB instead of the 6+ TB that I expected. For reference:

  • fdisk version: v2.12q
  • OS: SuSE Linux 9.3 (x86-64)
  • kernel: 2.6.11.4-21.14-smp

After searching around for awhile, I came across Linux Creating a Partition Size Larger than 2TB by Vivek Gite. The article recommended using parted; my system had GNU Parted 1.6.21 and it worked just fine. Do remember that you need to mklabel gpt. And now df -h lists the partition at a hearty “6.4 T”.

For some reason I have the urge to do a little jig and sing “Mo’ money, mo’ money, mo’!”

Image resolution in pixels vs DPI

When working with the print shop to create a poster out of a 3174 x 2153 pixel digital photo, I managed to get completely confused about DPI (dots per inch). I read a blog post called The Myth of DPI to educate myself, but that seemed to muddy the water even more for me. I must have been having a bad week because now the relation between pixel resolution and DPI is crystal clear:

pixels = inches * dpi

I wanted to print a poster that was 36″ wide, meaning that the DPI of the printout would be 88 (dpi = 3174 / 36 = 88).

Obviously, the more ink dots per inch you have, the crisper the image will look on a printed page. The printer recommended that I have 300 dpi to retain the quality of the image. What they didn’t make clear to me was that in order to have a 36″ wide poster at 300 dpi, I would need an image that was 10800 x 7200 pixels.

Adding to my confusion is that DPI is apparently part of the JPEG metadata. This means that you can change the DPI to whatever value you want. The key point is that raising the DPI reduces the printable image size, and lowering the DPI increases the printable image size.

All of this is spelled out in the The Myth of DPI, but for whatever reason I wasn’t getting it. Once I finally understood, I decided to bite the bullet and print the size I wanted, meaning that I would have to deal with 88 dpi. I think the resulting poster looks great. I mean, you wouldn’t put it up in an Ansel Adams gallery, but I don’t see any pixelation and it will be viewed mostly from afar. Time to frame this puppy and call this project done!

How to compile bandwidthd 2.0.1 on OpenBSD 4.3

I ran into numerous problems when trying to compile bandwidthd 2.0.1 on OpenBSD 4.3. The first problem was that, even though I had installed all the dependencies via ports, ./configure was still erroring out with:

checking for png_read_info in -lpng... no
configure: error: Bandwidthd requires but cannot libpng

Hunting around the web, I managed to get past that error, but then ran into this:

checking for gdImageCreate in -lgd... no
configure: error: Bandwidthd requires but cannot find libgd

The solution to both of these problems is this:

./configure LDFLAGS=-lz -x-libraries=/usr/X11R6/lib

I thought I was good to go at that point, but a make resulted in this problem:

Graph cycles through conf.l.c

`all' not remade because of errors.

I banged my head on this for some time before turning to the OpenBSD misc mailing list. Philip Guenther pointed me in the right direction:

The makefile is either buggy or assumes a non-POSIX make. Try it again with ‘gmake’. If you still get errors, yell at the bandwidthd authors.

I grabbed gmake from ports and voilà, success!

Volume discounts with PayPal Merchant Services

You’re probably not going to like this solution very much.

To set the scene, PayPal’s “Merchant Services” contains a fairly straightforward webapp to generate “Buy Now” and other such buttons. When we needed to sell a product at work, I figured that the steps would be as simple as:

  1. Generate the button
  2. Slap it on our website

Unfortunately for me, we were offering a volume discount (AKA, bulk rate) so that the price of the item was different depending on the quantity. After much mucking around in help pages and documentation, I found the “solution” in the PayPal Developer Community forums: Volume Discount with Shopping Carts

Long story short:

  1. Don’t use PayPal’s button generator
  2. Download the zipped HTML file referenced in the forum
  3. Read the HTML file and its source, giving you the knowledge to:
    1. Add some generically-written javascript functions to your site
    2. Create a custom HTML button (i.e., not generated by PayPal)
    3. Add the HTML inputs and inline javascript needed to drive the functions
  4. Tell your bookkeeper to double-check the payment amounts because any tech-savvy person could submit a form with whatever prices they please

The problem is that when using your own custom buttons, PayPal cannot do any validations on their end. You send them item names and amounts, and they’ll happily charge the customer for whatever happens to come across the wire. From my limited research, I think you can do this more cleanly if you implement your own shopping cart, and interface with PayPal in a more secure way.

But for the “simple” stuff, the best way to get started would be by perusing the PayPal Developer Central’s Simple Integration section. I found the HTML Variables for Website Payments Standard to be particularly useful. It really wouldn’t be that hard for PayPal to implement volume discount functionality on their end, but I suspect that maybe it’s something they are trying to sell in a “Pro” version.

sh: read: -p: no coprocess

Just thought I’d throw this out there since I don’t see many google hits on it. The problem (on OpenBSD 4.4):

$ read -p "Enter input: " MYVAR
sh: read: -p: no coprocess

Oh, of course, “no coprocess”! Surely, if I can somehow just add a “coprocess” then my read command will work… </sarcasm>

Anyway, I dug through info sh to see how the read command works on my OpenBSD system. Apparently one needs to format the command like this:

read MYVAR?"Enter input: "

jQuery: disable the submit button, but still send the button’s value

Solving the old user-hits-the-submit-button-twice problem is fairly easy using JavaScript and even easier using jQuery. Setting up a sequence like the following is no problem:

  1. User clicks the submit button
  2. Button becomes disabled
  3. The values of the form’s inputs are submitted

My problem is that disabling the submit button causes its value to not submit. Apparently no one else on the planet uses the submit button’s value because none of my Google searches revealed anyone caring about this in the context of using JavaScript to disable the submit button.

No doubt my custom framework could be better designed, but there are a few rare instances when I want to know whether a user submitted a particular form, or even which button in the form they used to fire the submit. If I disable the button, then I don’t get the button’s name/value and thus I lose information about what is happening on the user’s end.

I have two solutions to this problem, the first of which was inspired by Ryan’s comment to my initial draft of this blog entry.

SOLUTION #1: hide the submit button after click

$(document).ready(function() {
  $("input:submit").click(function (event) {
    $(event.target).addClass("Hidden");
    var form = event.target.parentNode;
    var msg = document.createElement("i");
    msg.innerHTML = "PROCESSING...";
    form.insertBefore(msg, event.target.nextSibling);
  });
  $("form").submit(function() {
    $(":submit:not(.Hidden)", this).attr("disabled", "disabled");
  });
});

You will note that I am making use of a CSS class that I’ve called “Hidden”:

.Hidden {
  display: none;
}

Now the sequence of events looks like this:

  1. User clicks the submit button
  2. The click listener runs a function that hides the submit button and replaces it with some italicized PROCESSING… text
  3. The submit listener then disables all other submit buttons
  4. The values of the form’s inputs are submitted, including the newly hidden submit button

SOLUTION #2: copy the name/value to a hidden element

This is my original, hacky solution:

$(document).ready(function() {
  $("input:submit").click(function (event) {
    var $submitName = event.target.name;
    var $submitValue = event.target.value;
    var $form = event.target.parentNode;
    $($form).append("<input type=\"hidden\" name=\"" + $submitName + "\" value=\"" + $submitValue + "\">");
  });
  $("form").submit(function() {
    $(":submit",this).attr("disabled", "disabled");
  });
});

Can you see what horrors I’ve wrought? Now the sequence of events looks like this:

  1. User clicks the submit button
  2. The click listener runs a function that copies the name/value of the clicked submit button to a hidden input which is appended to the form
  3. The submit listener then disables the submit button
  4. The values of the form’s inputs are submitted, including the new hidden input
  5. To the rest of my code, it appears as if the submit button’s name/value came through with everything else

Now don’t be stingy, man. Pass the data, dude.