fixing YouTube embed bleed through

I’ve been doing a fair amount of work with jQuery UI, making some dialogs to pop up over top of a campaign site I am doing for Jerry Wasserman. This activity was on a very short time line and it ended up being a nice little addition.

Things got a little exciting, though, when at the last minute I threw in the supporting video – because the video bled through the dialog, forcing the user to move things around until the video and the dialog don’t intersect.

The solution, it turns out, is to make the video opaque. Adding ‘ wmode=”opaque”‘ to the embed for the video is all it took to straighten it out. Thankfully, I found this almost immediately after I discovered the problem. Google to the rescue again!

I wonder why YouTube doesn’t do this in their generated embed code by default?

Scratching the Surface of Hudson

Hudson Logo

On my IBM front, I have set about installing a continuous integration server for one of our more elaborate projects. The project involves customizing a set of existing applications (Lotus Connections) by unpacking the production EARs, modifying their content, and repacking them. We do this to add in the ibm.com header and footer code, and to add/modify some of the default functionality to make it more amenable to an extranet implementation.

I chose Hudson, based on the fact that it is also a JEE application (meaning that it fits neatly into our existing infrastructure and skills) and because it integrates with our SCM – which is unusual, since our SCM is not one of the big ones in the game, shall we say.

Getting it working has been surprisingly easy.

I started with my personal server here in my aerie (my office is in the attic of a house that overlooks the slopes of the Wellesley Hills). I have a little box with Red Hat Enterprise 4 and WebSphere set up, so the infrastructure was all good. Here are a few things I picked up along the way:

  1. WebSphere has a version of ant tucked away in its classpath, so you have to adjust the application to load its classes first (because the WebSphere v. is old).
  2. It’s a good idea to set the HUDSON_HOME variable, because otherwise it ends up in /root — not exactly ideal!
  3. The auto-install of ant didn’t work, which may be because I didn’t enable the auto update function, so I just did it by hand.

I’d say that end-to-end, including getting around a handful of Sys Admin issues (I hadn’t touched that box in months!), it took less than four hours to get it building HelloWorld every time I changed the project in cvs.

Next steps are to get it integrated with CMVC (our somewhat antiquated SCM) and build some real projects.  I should have a bit more to report later on this week.

Verizon account is not a Credit Card

I just got my Verizon bill today and found some surprising charges on there. Ones from companies called, “Headwind Media, Inc.” and “OAS”. These charges were initiated by my young daughter when she went to a site called www.cmiprofiles.com. There, she filled out a form that included her phone number, and a variety of other facts, like mother’s maiden name and last four digits of her social security number that should have related to the phone number account, but obviously did not get checked. The bill included over $35.00 in new charges based on a child’s incorrect filling out of a form.

Verizon did not check the authenticity of the credentials provided to these people, they simply passed the charge along to me and trusted the bill. In the course of the conversation, I asked, “How could this happen?”. (Note that there are several stories on Ripoff Report about Headwind, so this scam is not unknown!) They simply said that they accept all charges associated with the phone number and pass them on. They did offer to block all such charges in the future, and I agreed. Now any such charges will turn into new bills, instead of new line items in my phone bill – much better, in my book.

Because my Verizon account is not a credit card account!

But Verizon is motivated to make it just that! If so, they need to completely renovate their approach to security to include some form of PIN or other security device that must be presented to a 3rd party (and passed back to Verizon) before they accept the charge.

My conclusion is that everyone should a) be especially vigilant about monitoring their Verizon bills, since they clearly have little to lose and much to gain from these scams and b) call Verizon and shut down 3rd party billing through their account.

Migrating Lotus Connections 2.0.1 to 2.5

In my IBM role I just got through a big migration of our communities platform (www.ibm.com/[activities|communities|dogear|homepage|profiles] and www-951.ibm.com/blogs) from Lotus Connections v2.0.1 to v2.5. This move involved not just an upgrade, but also a data center move.

Like the WordPress move I described earlier, my focus on this one was the data – getting it in the right place and upgraded to the new version.

Lotus provides tooling to upgrade the version of the database pretty much automatically – but it assumes that the database isn’t moving between data centers as part of the activity. Their most automatic tool, a Java Swing Wizard will handle all the databases at once through a nice GUI. I have two objections to using this. Firstly, it doesn’t work well over a WAN, because X is too chatty. Second, you don’t get to check results for each step of the process, so if things go wrong, you have to drag your butt through miles of log file text to find out what. So I used the manual process. This covered upgrading a database in place, which of course, does not map to our situation completely – our databases were half a continent away!

Our internal hosting providers work like a lot of others – they put the hands on the keyboard and do the work, but we webmasters get to make all the decisions. The upside of this is that they see how the system is put together before they take ownership of it’s day to day care and feeding. The downside is that a lot of up-front work is needed if you want a smooth transition.

In my case, this meant detailing each of the steps in the Lotus document above as well as dealing with moving the production databases (we used db2move and it worked like a charm!) and the production content repository.

[Interesting side note on the content repository: the directory structure involves some really long names and AIX's tar doesn't handle them right. I ended up loading Gnu tar on the box, which does.]

Lotus provides, as part of this migration, a system of Java applications that munge the data around once the new data structures are in place. These things take a pile of parameters: all the JDBC stuff, class names, and other items, and I could see us wasting a lot of time dealing with the inevitable typos when the hosting guys were executing them. So I wrote a set of wrapper scripts that boiled the parameter lists down to the bare essentials.

Here’s an example:

#!/bin/ksh

print -n "db2Admin password: "
read dbPass

parms="db2 BLOGS $DB_HOST $DB_PORT $DB_USER $dbPass"
java=$JAVA_HOME/bin/java
cpath=$DB2_JAVA_LIB/db2jcc.jar:$DB2_JAVA_LIB/db2jcc_license_cu.jar:lib/blogs.migration.jar
class_to_run=org.apache.roller.migrate.MigrateBlogsTo_2_5

# echo "$java -classpath $cpath $class_to_run $parms"
$java -classpath $cpath $class_to_run $parms

I used a single script to set the environment variables that were common to all of the scripts, again, just to keep things simple.

The Lotus code worked almost flawlessly. We had a little trouble with some widgets in Homepage, but I strongly suspect that it had to do with something we had done earlier, and not Lotus. The whole process, including moving the data and content repository, took about 9 hours, which is not that bad, considering that the document I wrote covered seven pages!

We are now up and running with Lotus Connections 2.5, which added Wikis and File sharing to the mix at:

Migrating WordPress to WordPress MU

I found myself working on a project last week to migrate a WordPress site to WordPress multiuser (WPMU).  I did the usual Google search for guidance and didn’t see much that encouraged me, I have to say. Posts, like this one were pretty helpful. But I wanted a process that could be clearly articulated, practiced a couple times on a test system, and then executed in something like 10 minutes, to keep the outage as short as possible. (The site has an active world-wide following.)

I had a big advantage – just one blog was being migrated, so no mess around which author gets what privileges on which blog. Merging several multi-author blogs into a single WPMU site would be more work, for sure.

The approach I took is different from any I saw elsewhere. I chose to build a second database for WPMU and used a script to pull the data out of the original WP db into the WPMU db. This approach allowed me to commit the data migration process to code, which can be tested repeatably.

At a high level the process of migrating the site went like this:

  1. Create a new database for WPMU
  2. Redirect all users but me to an under-construction page
  3. Install WPMU (preloaded with all of my plugins and themes) to initialize the database
  4. Use a SQL script I wrote to copy content from the old WP database into the new WPMU tables
  5. Relocate the files in the wp-content/uploads directory to the wp-content/blogs.dir/1 directory
  6. Jump into the WPMU administration console and fix up the configuration
  7. Test

The script I created is for an average blog with no tables added for plugins. The key message, as is noted in most posts on this subject is that the blog content tables are named using the convention: ‘wp_blogid_table‘. Users and options, however, remain in a single set of tables for all blogs.

Here is the SQL script:

-- users
-- purge users installed by WPMU
DELETE FROM new_wpmu_db.wp_usermeta;
DELETE FROM new_wpmu_db.wp_users;

-- copy users from WP db
INSERT INTO new_wpmu_db.wp_users(ID, user_login, user_pass, user_nicename,
user_email, user_url, user_registered,user_activation_key, user_status, display_name)
(SELECT ID, user_login, user_pass, user_nicename, user_email, user_url, user_registered,
user_activation_key, user_status, display_name FROM old_wp_db.wp_users);

-- copy usermeta
INSERT INTO new_wpmu_db.wp_usermeta (SELECT * FROM old_wp_db.wp_usermeta);

-- fix user privileges
UPDATE new_wpmu_db.wp_usermeta SET meta_key=REPLACE(meta_key, 'wp_', 'wp_1_');

-- clean out generated content from primary blog db
DELETE FROM new_wpmu_db.wp_1_comments;
DELETE FROM new_wpmu_db.wp_1_links;
DELETE FROM new_wpmu_db.wp_1_postmeta;
DELETE FROM new_wpmu_db.wp_1_term_relationships;
DELETE FROM new_wpmu_db.wp_1_term_taxonomy;
DELETE FROM new_wpmu_db.wp_1_terms;
DELETE FROM new_wpmu_db.wp_1_posts;

-- copy posts from oritinal blog db
INSERT INTO new_wpmu_db.wp_1_posts (ID, post_author, post_date, post_date_gmt,
post_content, post_title, post_excerpt, post_status, comment_status, ping_status,
post_password, post_name, to_ping, pinged, post_modified, post_modified_gmt,
post_content_filtered, post_parent, guid, menu_order, post_type, post_mime_type,
comment_count)
(SELECT ID, post_author, post_date, post_date_gmt, post_content, post_title,
post_excerpt, post_status, comment_status, ping_status, post_password, post_name,
to_ping, pinged, post_modified, post_modified_gmt, post_content_filtered, post_parent,
guid, menu_order, post_type, post_mime_type, comment_count FROM old_wp_db.wp_posts);

-- copy postmeta from oritinal blog db
INSERT INTO new_wpmu_db.wp_1_postmeta (SELECT * FROM old_wp_db.wp_postmeta);

-- copy links from oritinal blog db
INSERT INTO new_wpmu_db.wp_1_links (link_id, link_url, link_name, link_image,
link_target, link_description, link_visible, link_owner, link_rating, link_updated,
link_rel, link_notes, link_rss)
(SELECT link_id, link_url, link_name, link_image, link_target, link_description,
link_visible, link_owner, link_rating, link_updated, link_rel, link_notes, link_rss
FROM old_wp_db.wp_links);

-- terms, taxonomy & relationships
INSERT INTO new_wpmu_db.wp_1_terms (SELECT * FROM old_wp_db.wp_terms);
INSERT INTO new_wpmu_db.wp_1_term_relationships (SELECT * FROM old_wp_db.wp_term_relationships);
INSERT INTO new_wpmu_db.wp_1_term_taxonomy (SELECT * FROM old_wp_db.wp_term_taxonomy);

-- comments
INSERT INTO new_wpmu_db.wp_1_comments (SELECT * FROM old_wp_db.wp_comments);

The only slightly tricky part in the whole script was figuring out how to fix the user permissions to point at the right blog.

Welcome!

dinosaurLet me introduce myself and what I intend to do with this blog.

I am a dinosaur in the IT industry, and the son of a dinosaur.  On occasion, while I was growing up, my Dad would pull out his personal AND circuit made with tubes.  It was something on the order of 1″ by 4″ by 6″.  One AND circuit.  Yeah.  And now the CEO of IBM is talking about billions of transistors per person on the entire planet.

IBM, being a big firm, is the kind of company you can have several careers in.  I am a classic example of this, having spent 8 years designing mainframe CPUs, 2 years in marketing, and nearly 20 years in IT services, before joining my current team – the corporate webmasters.  (Talk about your misnomers!  A team of some 20 people spread around the world, “mastering” IBM’s 4-million+ page website!  We’re more like webwatchers!)

During my career, I have seen the explosion of the PC, the implosion of the mini-computer, and the amazing endurance of the mainframe.  I have seen user experience go from green letters on a black screen to 3D immersive experiences.

I have personally developed software on OS/2, NET.Commerce (a C++ commerce engine that preceeded WebSphere), Java, J2EE, Flex, and several other platforms I forget.  I’ve designed databases in Db2, Oracle, SQL Server, and MySQL.  And I’ve led teams as small as two and ad big as 100 through projects.

So, what do I plan to do with this blog?  Well, first of all, as a consultant, I never stop learning.  But I am finding it harder to keep track of everything I have learned, so I plan to use this as personal storage of particularly good methods, tricks, or techniques that I pick up.  Especially those things that I expect to only use once in a great while, but are not all that easy.

So look for a wide-ranging set of posts on a range of topics as broad as my experience and as deep as the problems I deal with as a senior software engineer.  And, please, let me know when my tendency to take the road less travelled has sent me down a rat-hole!  That is why it’s a blog and not just a database.

Thanks for coming!