Tuesday, August 27, 2013

Securely wiping a classic Mac OS 9 PPC computer

I found an Apple iMac G3 that had been in my basement for 15+ years! It has 64mb of RAM which was enough to run the apps of 1998 (or a single Firefox tab in 2013). I wanted to get rid of this old Apple junk so I could buy newer, more expensive Apple junk. But to do that, I had to ensure the disks were securely wiped.

Say goodbye to the iMac.

Thankfully the popular Darik's Boot and Nuke (or DBAN) tool is available for the PowerPC (PPC) platform, which you can grab from SourceForge. The latest version of DBAN for PPC is 2.0.0. I can't imagine many people perform secure wipes of pre-Intel Macs these days, but apparently I'm one of 11 people this week who have downloaded DBAN for PPC!

I'm guessing it's me and 10 web crawlers.

DBAN gives you a few options for wiping a disk, depending on how paranoid you are. You can pick the source of entropy, the Pseudo Random Number Generator (PRNG), how many passes, and whether to verify the passes. A lot of options for formatting a disk: had I designed the DBAN interface, I'd have just specified paranoid, ultra paranoid, Fox Mulder, Security Architet, Fox News Anchor.

I chose a DoD 5220.22-M (aka "DoD short") wipe which is fancy terminology for overwriting the contents of the disk with random information three times, and verifying that the write completed successfully. I used the default Mersenne Twister PRNG, which is a fancy system for ensuring that the random numbers are indeed random, and not just the number nine.

A random Dilbert comic.
I thought the wipe was going fast: 40 minutes in and 40% done, then I realised the disk size was only 6 GB! We have it good these days. Now let's watch a blue screen which isn't Windows crashing due to me overclocking the video hardware!

The data will become irrecoverable...BECAUSE THE DISK WILL

And good things come to those who wait. According to the hardware clock powered by a dead battery, the year is now 1956 and I have spent negative 56 years waiting for the wipe to complete. Forget saying hello to the iMac: say hello to the UNIVAC.

Wednesday, May 8, 2013

The Flex Wing: how to use a license file to bring strategic tactical immense MBA value to your business and stuff

This post is one in a series of irreverent blog posts on the topic of software licensing. 

FlexLM and Furious: setting up a license server
FlexLM and Furious: restricting FlexNet license usage
FlexNet, FLEXnet, FlexLM, FLEXlm, it’s the same product, stop renaming it you crazy marketing people: an overview.


Software licensing is a war between your cardigan-wearing procurement group and the software vendor sales team (usually salespeople wearing pinstriped suits who fly private jets). License file generation is an extension of this negotiation, which is why I've dedicated a quarter of this blog post to discuss a third of the topic. But let's first begin with license files, without which we wouldn't have license servers, vendor daemons or headaches.

Requesting the FlexNet license file

Up to 167% of a vendor account manager's time can be spent issuing license files, issuing updated license files, guiding the customer through updating their license files, explaining licensing restrictions, forcing their internal licensing group to reissue an incorrect license file, listening to customer complaints about license files, determining whether the customer complaints should be referred to the police, and secretly wishing their internal licensing group could hear the customer complaints.

Requesting a new license file usually involves filling out a long form that contains lots of personal information that, quite frankly, scares me. They'll ask things like what the MAC address of your license server is so that you can't give it to your friends (everyone on the internet). If you are getting a license file reissued, the vendor will make you fill out the same form except charge you $190. This is to pay for the cost of reissuing the license, which takes about 5 minutes for them to do after you've spent 3 weeks getting a purchase order.

Once you get the license file, you should immediately put it in a random location you'll forget, probably the digital equivalent of where you keep your receipts or birth certificate. Although license files have the file extension of .lic, be sure to name it something helpful like ntoskrnl.exe or latestLicenseUpdatedtoV2-NEWESTDontUseIGNORE-MUSTUSETHIS.lic. If you rename the license file to something descriptive like the name of the vendor daemon (ie. abaquslm.lic), you're just showing off. If your application has multiple license files (eg. ESRI), be sure to place them in different folders on different data drives. That way, people who don't understand your random license file layout will know that you have mad licensing skills and then join your posse.

The vendor daemon is adskflex.exe.
The license file is adskflex.lic.
It's in a folder called adskflex.
When the license file is updated, a backup copy is made in the Backup folder.
You don't have to be a rocket surgeon to figure this out.
(a rocket surgeon is a guy like Norman Einstein)

Negotiating FlexNet license features

Just as the vendor sales team screwed you during negotiation, the licensing team will try to screw you during delivery. Remember, it is the job of the vendor licensing team to deliver as little functionality as contractually obligated in order to open future sales opportunities.

You: "We purchased ten BizzaroCAD licenses. Please give me a license file so my Australia and Mumbai teams can work. Some team members use BizzaroCAD while traveling."

Software vendor: "I can give you a license file which is time zone locked to Antarctica with borrowing functionality disabled. Everything should be fine for your five person team."

You: "Five licenses? We purchased 10! And you agreed to enable license borrowing!"

Software vendor: "You should talk to our sales team to get those features."

On the other hand, you may be lucky and have a naive software vendor. Some vendors in the medical imaging space like to be "lenient" to their customers because they "help save lives". Amateurs! You must abuse their trust so they can learn and their culture can progress to that of Microsoft's. If you don't abuse their trust, how will they cope in the real world? Here's an example.

Software vendor: "I see you are licensed for 10 concurrent users! Let me gen..."

You: "I want a license file allowing 5000 concurrent users!"

Software vendor: "That is an unreasonable request."

You: "YOLO"

Insist that the licenses aren't MAC address locked to any server. If the vendor hesitates, point them to this VMware KB article then laugh at them. When they capitulate and generate a license file that isn't server locked, post the file on The Pirate Bay. This will demonstrate who calls the shots: you, and the hamster on the wheel in your head. Or the hamster who manages enterprise software licensing at your organisation. Either or really.

See that 'ANY' and 'permanent'? That's example of a licensing WIN.
Oh, and it's not a real license file. HJK3AFH4 is only 8 characters,
the real one is 13 characters. You can test if you don't believe me.
But if you don't believe the word of a person on the internet you've never
met before, who can you trust?!

Serving the license file

Now that you've got your license file, you'll need to load it so that idiots can use their stupid license-locked applications. This is done with the FlexNet License Server (lmgrd.exe) of which there are many versions in common circulation. The good news is that it's easy to check the version (just right-click on the file in Windows Explorer and look for the version). The bad news is they all suck.

The FlexNet License Server (lmgrd.exe) is a standalone executable: you can place it anywhere and it will work. You can easily upgrade the lmgrd.exe license server too: if you've got a newer version, just replace the old executable with the newer version you downloaded. Of course, this will require you to stop the license server. Watch out.

I would rather play this game than restart the licensing server at...well, any company.
Upgrading the FlexNet license server

Backward compatibility is an important feature of computers. The backwards compatibility features of the Xbox 360 allowed you to play older Xbox games (and if you JTAG'd your console, PlayStation, Super Nintendo, Nintendo, Atari and ColecoVision games too). License servers are similarly backward compatible, meaning that a vendor daemon compiled with an earlier version of the framework will work with a newer license server. This means your license server version needs to be equal to or newer than the FlexNet framework used to create the vendor daemon. For example, if your Autodesk licensing daemon is version 9.0, you need a license server (lmgrd.exe) version of at least 9.0. Running FlexNet license server version 8.0 with a 9.0 vendor daemon will cause your server to burst into flames, which may or may not wake up your datacentre and facilities managers.

Generally speaking, it's better to run the newest version of the lmgrd.exe license server. You'll get access to the new features, and it's more stable due to Flexera phasing out parakeets from their development team in favour of humans. The latest version of lmgrd.exe and the LMtools license management application is always available here. Don't ask me why the domain is globes.com. I think that was the name of Flexera three acquisitons ago. I miss those parakeets.

Upgrading the vendor daemon

As the name would suggest, each vendor will have their own vendor daemon. If the vendor is an software company that has lots of acquisitions, they could have multiple vendor daemons for their products (I'M LOOKING AT YOU AUTODESK!). Thankfully, vendor daemons are usually easy to find on the vendor website. If you're lucky, the vendor daemon (such as this one from Autodesk) will be available as a small standalone 300kb download. If you're unlucky (probably you if you're reading this post), the vendor daemon will only be available in the 8.4gb source media file in a members only part of their website which requires a secret handshake from an account manager.

Making sure licenses still work after you've upgraded the FlexNet license server/vendor daemon

It's important that you use the most recent vendor daemon and FlexNet license server as possible, because newer versions support newer features and keywords. Did you just try to use the PRIMARY_AS_MASTER keyword with a vendor daemon compiled with version 9 of the FlexNet licensing framework? You imbecile! Didn't you know that the PRIMARY_AS_MASTER keyword wasn't introduced until version 10?! Didn't you drink enough milk as a child?!

Getting LMtools (lmtools.exe)

You might think LMtools is a badly written piece of crap.

Anyway, thanks for reading! I hope to bring some humour to the most boring topic in IT. Probably not.

Thursday, March 14, 2013

Chess in C (Part 6) - Potential moves of a bishop: up-right

This post is a continuation of Chess in C (Part 4). No fancy introductions or recaps. If you don't read that, you won't understand this.

Radiating up-right

Mission: write an algorithm that returns the up-right diagonal from a bishop in position (X,X).

We need to get (2,5), (1,6) and (0,7). We can modify the algorithm used to figure out the up-left diagonal as follows
  1. Start at the last square and iterate through the board backwards
  2. For each square, check if the upper-right square is within the board
    1. If it is, check if there's a bishop or breadcrumb in the upper-right square
      1. If there is, this square is a potential move. Mark this square with a breadcrumb.
  3. Repeat until you reach (0,0).
Just like in the up-left algorithm, we need to iterate through the board backwards. If we iterate forwards, we won't pickup all the potential moves. Here's an illustration: start at square (0,0). Ask yourself, "Is there a bishop or breadcrumb in the lower-left diagonal square?" Progress to the next square. Ask yourself the same question. At position (0,7), your answer will still be no, even though (0,7) is a potential move!

You call yourself a bishop?!.

This is what happens when we iterate backwards.

The code to implement this algorithm is similar to the up-left diagonal. Unfortunately, it's a little too similar!

If we reuse the code, the breadcrumbs for each of the algorithms will trip up over each other! The solution is to modify the macros and board drawing code to differentiate between the breadcrumbs of each algorithm. I've made a few more POTENTIAL_BISHOP_MOVE macros and appended _UL (upper-left diagonal), _UR (upper-right diagonal), _DL (down-left diagonal) and _DR (down-right diagonal) to them. Here's the code you'll need to begin this lesson.

Now it's time to code up this algorithm.

The code is similarly straight forward. Lines 4 and 5 contain the for loops which iterate through each element in the array backward. Line 8 prevents us from checking the row below or the cell to the left if it doesn't exist. Imagine we're in square (2,5). Because we want to know if the square is a potential up-right diagonal move of a bishop, the bishop must be in the lower-left direction. Here's an illustration.

Put your finger on square (2,5). Yes, it's covered by an X. Pretend you don't know where the bishop is.
If you were trying to find out of the square you're in (2,5) was up-right of a bishop, which way would you search?

The location of the bishop relative to the X is (+1,-1). We're at (2,5), so we're checking if (3,4) exists. Which it does. But what if we were at square (7,0)? Square (8,-1) definitely doesn't exist, and if we try to check that square we'll exceed the bounds of the array. Which is bad.

Line 10 checks the actual cell for a bishop or a breadcrumb. If it does, line 12 marks the square with a breadcrumb for the board drawing code to interpret. Time to test!

Bishop in position (0,0).
You know what we're not doing?
Testing if there's a bishop in (1,-1)

Bishop in position (4,4).
It looks like the algorithm has been implemented correctly.

Bishop in position (3,4).
That looks nice!

Bishop in position (4,7).
We're testing an edge case. It works.

Bishop in position (7,7).
Another edge case to test.
And it works!
Done! Here's the code.

Sunday, March 10, 2013

Chess in C (Part 5) - Potential moves of a bishop: up-left, cardinal, pope

On a chess board, the bishop can move diagonally forward or back by any number of squares. I've never seen a bishop in person, but I can say with a high degree of certainty that they don't move diagonally in real life. But just to be on the safe side, if I ever meet a bishop in real life I'm going to stand directly infront of them so they don't bump into me. Wikipedia has a technically correct but literally impenetrable explanation of how bishops move on chess boards, but I believe I've bested the Wikipedia community with my diagram.

Potential moves of the bishop,
aka "the diagonal piece"

Given a square on a chess board, how do we draw the potential moves of a bishop? In the diagram above, the bishop is in position (3,4). There are four possible directions the bishop can move in.
  • Up-left: (0,1) (1,2) (2,3)
  • Up-right: (0,7) (1,6) (2,5)
  • Down-left: (4,3) (5,2) (6,1) (7,0)
  • Down-right: (4,5) (5,6) (6,7)
Each direction radiates outward from the bishop like rays from the sun. To make this easy, work on each diagonal separately.

Radiating up-left.

Mission: write an algorithm that returns the upper-left diagonal.

The bishop is at (3,4). We need an algorithm that returns us the positions (0,1) (1,2) (2,3). If the bishop wanted to move up-left one square from (3,4), it would be in (2,3). If it wanted to move up-left two squares, it would be in (1,2). If it moved up-left three squares, it would be in (0,1). It seems simple enough to generate the list of potential moves: you start from the bishop, then work backwards from there

Now let's implement it. Remember the code used to iterate through each square on the board from part one of the blog post? I'll post it here.

The code iterates uses two for loops to iterate through each square on the board. The code starts at board position (0,0) and iterates to the end of the row (0,7). It repeats this until it reaches position (7,7). We used this code to clear the board (overwrite each array element with a zero) and also to draw the board. Here's an illustration of how that code works.

The catch is that you can't use this code to work out where the bishop's potential moves are. Imagine the bishop is at (3,4). When the iteration code reaches (3,4), it will be too late already: you'll have passed some of the squares which are potential bishop moves. The iteration code is only useful if you're trying to work out the potential down-right bishop moves. To work out the potential up-left diagonal bishop moves, you need to work backwards.

In the first post of this blog series, I put some code in the original program to iterate through the two-dimensional board array backwards, just for fun. Here's the code to iterate through the board backwards.

Here's our logic. It's incorrect, but let's run with it for now.

  1. Start at the last square and iterate through the board backwards.
  2. For each square, check if there's a bishop in the lower-right square.
    1. If there is, mark this square as a potential move.
  3. Repeat until you reach (0,0).
  4. All potential diagonal up-left moves have been marked.

Let's model this theory before we code it. If you need to, put your finger on position (7,7) on the diagram and ask yourself the question: for this square, is there a bishop in the lower-right square?

This algorithm correctly identifies (2,3) as a potential move, but not (1,2) or (0,1) which are also potential moves. Close, but no cigar. We can modify our algorithm to mark some squares with breadcrumbs. A breadcrumb is a marker for a potential move. Why do we need breadcrumbs? Well, it's obvious that (2,3) is a potential move and our algorithm works for this. But this check doesn't work for (1,2). What we can do at (2,3) is drop a breadcrumb: a marker that can be checked for when we get to (1,2). We can modify the algorithm to drop and detect breadcrumbs as follows:
  1. Start at the last square and iterate through the board backwards.
  2. For each square, check if there's a bishop OR breadcrumb in the lower-right square
    1. If there is, this square is a potential move. Mark this square with a breadcrumb.
  3. Repeat until you reach (0,0).

Let's model this theory. Again, put your finger on the square and ask the question, is there a bishop or breadcrumb in the lower-right square?

Hey, this works! Time to pop the champagne? Well, no. There's still another flaw in this code. When you're at position (7,7), you're asking the question, is there a bishop or breadcrumb in the lower-right square? In this instance, the lower-right square is (8,8), which doesn't exist. The memory allocated outside of the array could be anything. If you check for position (8,8), you'll get undefined behaviour: when you run your program, board[8][8] could be equal to 0. The next time you run, it could be equal to 5. Or 9. Or 42. I've described why this happens in part two. Basically, you don't know what information is stored outside of the array. All you need to know is that you must not check array locations that don't exist. This will require one final change to the algorithm.

  1. Start at the last square and iterate through the board backwards.
  2. For each square, check if the lower-right square is within the board
    1. If it is, check if there's a bishop OR breadcrumb in the lower-right square
      1. If there is, this square is a potential move. Mark this square with a breadcrumb.
  3. Repeat until you reach (0,0).
Let's code it! I'll also put the code containing #define lines that contain the cell to piece mapping. This is so you know that an array element with value 5 is a bishop, and value 50 is a breadcrumb for a bishop.

Here's an implementation of the algorithm.

Line 1 and 2 contain the for loops that perform the iteration. Because we are iterating backwards, the conditions of the for loop are slightly different.

  • Instead of i being equal to 0, i starts at 7 (the end).
  • Instead of i iterating until 7, i iterates while it is larger than or equal to 0.
  • Instead of incrementing, i decrements.

Line 8 does the bounds checking. The if statement performing the bounds checking has two checks: (j+1 != 8) and (i!=7). If j+1 is equal to 8, that means you're in the final column, so don't check further! If i is equal to 7, you're in the bottom row so don't check further! Line 11 checks whether the down-left square has a breadcrumb or a bishop. Line 11 is only executed if the bounds checking in line 8 is successful. And finally, if all these tests have passed, line 13 marks the square as containing a breadcrumb. Here's the code so far. Copy and pasta it into your IDE and hit compile!

Let's see the output.

Bishop in position (0,0).
This is easy.

Bishop in position (4,4).
Yay, it works!

Bishop in position (3,4).
Woo hoo!

Bishop in position (7,7).
It can move right across the board. Great!
No nasty errors from trying to check array elements
that don't exist. 

Bishop in position (4,7).
It works! And no nasty out of bounds errors.

Great! We've written the code that works out the potential upper-left diagonal moves of a bishop. This was the most difficult diagonal move of the bishop to work out: you needed to combine your knowledge of iterating backwards through two-dimensional arrays, bounds checking, and algorithms. It's easy from here on in! In the next post, I'll discuss how to code the other potential moves of the bishop.

Other posts in this series

Chess in C (Part 1)
Chess in C (Part 2) - Insert Pawn Pun Here
Chess in C (Part 3) - Rook, Rooks, Rookies, Wookies, same thing
Chess in C (Part 4) - I'm asking for input
Chess in C (Part 5) - Potential moves of a bishop: up-left, cardinal, pope

Saturday, March 9, 2013

Chess in C (Part 4) - I'm asking for input

Input validation is extremely important. Whether it's a C application or a public-facing website, if you're taking input from a user, you are giving that user an invitation to input garbage. If the user is required to input their name, they'll input their phone number. If required to choose between 1 to 3, they'll enter negative 42. If required to select Yes or No, they'll find a way of typing in their cat's name. And that's if you're lucky.

If you're unlucky, it'll be an attacker trying to overflow your input buffer to break your application so they can steal your password database. But if you're lucky, it'll just be your tutor/lecturer/coworker trying to teach you a lesson. One of my C assignments at university involved writing code to parse command line arguments. The lecturer had warned us that we should treat all user input as hostile, and that our code would be tested for invalid user input. I believed I had thought of every category of invalid data and asked the the tutor to confirm my code was perfect. He looked at my code then asked, "What happens if you specify an argument and leave it blank?" My response was along the lines of...


This post is part three of the Chess in C series and covers input validation. This series is for beginners. If you know how to iterate through two dimensional arrays and write basic algorithms, this isn't the blog post you're looking for! Unless you want to feel smug and superior.

Chess in C (Part 1)
Chess in C (Part 2) - Insert Pawn Pun Here
Chess in C (Part 3) - Rook, Rooks, Rookies, Wookies, same thing
Chess in C (Part 4) - I'm asking for input
Chess in C (Part 5) - Potential moves of a bishop: up-left, cardinal, pope

So last time I left you, I challenged you to take input from the user then draw the position of the rook. I'll explain the answer, then I'll post some working code. To begin, here's a reminder of the possible moves of a rook. In the following diagram, the rook is in position (3,4).

A representation of an array.
NOT a Cartesian plane. Do NOT draw this in a maths exams.
You might think, "What the heck? Why isn't (0,0) in the bottom left-hand corner like my maths textbooks?" Remember, this diagram is not a Cartesian plane. It's a representation of a two-dimension array in C that happens to look like a chess board. And the top array value is (0,0), because in C we start counting at zero.

Okay, so you want to take input from the user? Ask for it! Here's one way of doing it.

There are lots of ways to get input from the user. Asking a programmer the best way of getting string input from a user is like asking which car is the best. You'll get a long winded answer and if you're unlucky, everyone in earshot will hear the question and give you their opinion as well. The method I've written does a simple check to see whether it's a number, check whether the user didn't just press enter (which would appear as a '\n' in position zero of a character array) and some simple bounds checking. It's a quick and dirty way of getting a row and column number, and you'll see why it's dirty later. Don't reuse this code if you're writing the user interface to a insulin pump or a medical device.

Now, let's glue it all together. Copy and paste the following code into your IDE and compile it.

Let's run it with some inputs and see what we get...

Seems legit to me.

It's always good to do "bounds testing". Test the maximum column value allowed. 
Test the maximum row.

Test the maximum row and column.

Test one over and one under the bounds.
Hey, just wait...we're getting some strange output here!

Test one invalid input and one valid input.
Strange input, again!
Test some letters.
...and remove the pickle.
I pressed enter without typing anything.
You'd be surprised how many students programs break
when you just press enter at prompts.

It seems like the code works, but invalid input can result in strange results! How do we avoid a situation where invalid output is displayed? A few points:

  • If the user answers the first question (for the row number) incorrectly, you won't be able to draw the board correctly so there's no point in asking the second question.
  • If the user answers the first question correctly but the second question incorrectly, there isn't drawing the board.
How best to implement this decision tree? Well, the easiest way is to nest the code for the second question in the code path executed when the user answers the first question correctly. This method would be both straightforward and easy but horrible to maintain. The decision tree is simple today, but what if you asked a third question? Or a fourth? You could have if statements nested in if statements nested in if statements! I know Chess in C is just an introductory level blog series, but I don't want you to get into the habit of writing unmaintainable code!

The questions we need to ask and the target state.
But how do we implement this?
A more maintainable way to handle this situation would be to use an additional variable for flow control. You could create an extra variable called badAnswer which is initially set to 0. If either of the questions were answered incorrectly, badAnswer would be set to 1. You could then wrap an if/then statement around any code you only wanted to execute if the answers given weren't bad. This would stop the second question from being asked if the answer to the first question was bad, and it would stop the board from being drawn if the answer to the second question was bad. Here's the code. Copy and paste and experiment.

Now let's retry the tests that broke the code.

Seems ok this time.

Also seems ok this time.

Also also seems ok this time.

No cheese burger for you!
I pressed enter when prompted. It works!

Great! We've rewritten the code so that if incorrect inputs are given, the program will close gracefully without showing a board that looks like gibberish.

Friday, March 8, 2013

VMware training is expensive in Australia: go to Singapore!

Vendors have a history of overcharging Australians for software. Someone realised it was cheaper to fly to the United States to purchase Adobe Creative Suite than to purchase it locally. Unfortunately, it’s the same case with VMware training.
VMware vSphere: Install, Configure, Manage – the course you have to sit
This course (also known as the VMware ICM) is required if you want the VCP (VMware Certified Professional) certification. The course is mandatory if you want to be certified: if you haven't attended the course, you can't be a VCP even if you passed the exam. The good news about this arrangement is that every VCP has a minimum common level of knowledge, and the VCP hasn't been watered down like the equivalent Microsoft certifications. The bad news is that the course is AUD$3850 + GST. It's a nice cash cow for VMware, but not so good if you’re paying for the course yourself (like I did).

Why would you pay for the course yourself and not have your employer pay? Maybe your employer isn't interested in upskilling you in virtualization, or you're a contractor, or just someone trying to break into an infrastructure role. Getting VCP certified is a serious commitment and I hope to save you a few dollars if you're not lucky enough to have your training paid for.

All of VMware's training courses are listed on myLearn. If you click the Find a Class link, you'll have the option of searching for ICM. Here's a screenshot of the course details for ICM in Sydney.

Unfortunately, a 10% GST is applicable. 

However, the same course is available in Singapore for USD$2620, or only AU$2580! Is it cheaper to fly to Singapore, stay 7 nights, do the ICM course, then fly back for less?!

$3850 vs $2620? That's a saving of at least...fifty bucks!
It may very well be! Let’s put my theory to the test. To begin, the Australian price we need to beat is $3850 + GST (which is $4235, but I'll assume you don't own a company to claim GST). The course I've selected is at the VMware Singapore office on Temasek Boulevard. It starts on the 11th of March, but I like to arrive in a city a a day or two beforehand so I can settle in. If you were to fly from Sydney on the Saturday beforehand and return the next Saturday, it would cost you...

...after the customs user fee, immigration user fee, APHIS fee, federal transport tax fee,
security fee, passenger movement charge, passenger service charge, international surcharge,
facility charge and credit card fee, that comes to...
...$558.30, which leaves a few dollars for a hotel. The Porcelain Hotel is nice and it's close to the Chinatown NE4 MRT station, which is only four stops away from the Esplanade CC3 MRT station. Esplanade MRT is directly below the VMware Singapore office.

 You could stay at Hotel 81 for half the price,
but that place is a little strange.

The Porcelain is small and quirky, but at $953 it's very reasonably priced and has all the expected luxuries. In summary:

Cost of course in Australia if you don't own a company: $4235 ($3850 AUD + 10% GST)
Cost of course in Australia if you own a company: $3850

Cost of course in Singapore: $2620 USD ($2580 AUD, as at 2013-03-06 via Citibank)
Cost of return flights: $558.30
Cost of hotel for 7 nights: $953
Total: $4091.30

If you don't own a company and you're unable to claim GST, there's a $143 benefit in flying to Singapore, staying 7 nights, and attending the course at VMware's Singapore office! If you own a company, the GST rebate lets you attend the course approximately $250 cheaper than doing it in Singapore. But if I were you, I'd still do the course overseas because
  • You'll get to meet people in the wider Asia Pacific VMware community you wouldn't normally meet. It's a good opportunity to network with other IT infrastructure professionals from a different region and see what their challenges are.
  • The quality of the instructors is the same worldwide. It seems that the VCP instructors fly around the world.
  • You'll be interrupted by phone calls if you attend the course in Australia. How many times have you attended course and seen people miss important lessons because they answered work phone calls during class time?
  • The concepts taught in the ICM course are important and you'll be more focused if you don't have to worry about your usual day to day urgencies. The urgent always seems to overtake the important.
  • The VMware Singapore office has a well stocked pantry with plenty of drinks and Toblerones!
If you're considering going to Singapore for the VMware ICM but want to reduce the price, you could use airbnb and stay in someone's spare room. And if travelling isn't an option, you can attend the course online via WebEx: it's the same price as classroom delivery, without any of the interaction.

Whether you attend the course in Australia, over WebEx, in Singapore, or any country, there's a lot of content in the VMware ICM to cover. And if you're new to VMware, be sure to pick the method of course delivery which is most conducive to your learning. It might not be the cheapest, but I hope it is!

Wednesday, March 6, 2013

The Hong Kong guide to the Paris guide to IT infrastructure

There are many metaphors for enterprise architecture. The most common one I've heard is that enterprise architects are the glue between an organisation's strategy and execution. This reads well as a LinkedIn status update or tweet, but you could say the same about project managers responsible for executing strategic projects, or CFOs who pick strategic projects and ensure they're funded. Whenever someone asks for my view on the role of enterprise architects, I like to say I'm a student of the "Paris" school of enterprise architecture.

The Paris Guide to IT architecture was an article published in the McKinsey Quarterly in 2000. It talks about the history of Paris and how the city's architecture and buildings have a consistent feel and theme despite architects who've had over 200 years to "improve" it. The consistency of Paris is used as a metaphor for IT architecture: just as the roads and public transport of Paris unite the buildings, define the landscape and set the terms for evolution (Laartz, 2000), enterprise architecture involves the systems and frameworks that unite applications and provide a way of integrating and accommodating disparate systems in a coherent way. Although it doesn't say it, the article hints that enterprise architects are the town planners of IT. I've never visited Paris, but the concept resonates when I compare Hong Kong or Singapore to lesser planned cities in Asia.

The IFC check-in service in Hong Kong strikes me as an example of a system that exists because other systems have been architected well. The Hong Kong International Airport (HKIA) allows you to check-in to your flight and drop your bags in the city, leaving you with a boarding pass and the opportunity to spend your day shopping and exploring the city instead of waiting in an airport lounge surrounded by stereotypes. While you do your shopping, your bags are securely transported to the airport, saving you the stress of carrying them or having to stop at your hotel before the airport.

International Finance Center (IFC): the building Batman jumps from in The Dark Knight.

The architecture for IFC check-in relies on the availability and openness of other systems like
  • airline systems, to facilitate check-in at IFC.
  • airport systems, to provide airport services including security, timetabling, messaging, alerting.
  • the Airport Express rail system which provides mass transit from IFC (or any station) to HKIA
  • luggage transport systems that move traveller luggage securely from IFC to the airport and provide handoff to the airport luggage routing system
  • network systems, to facilitate secure and reliable communication with the airport
  • et cetera
The actual specifics behind system integration isn't enterprise architecture: that's application architecture. The fact the required functionality and systems were available was because of enterprise architecture. During the architecture of the baggage system, the application and infrastructure architects may have developed the best solution for accepting baggage from an on-premise airline check-in desk and delivering it to a plane. But was their solution service-oriented? Was it open? How flexible would the solution be if a new requirement for bag drop from off-premise sources (such as the IFC check-in) was introduced? Or if bag drop from hotels was introduced? Upfront completeness of requirements is important, but part of enterprise architecture is knowing when to keep the door open and how to do it.

A town planner might know that every premise requires lines for sewage, electricity, water, gas and telephone, but they still might keep the door open for future services by requiring ducting infrastructure from streets to the home. If a new technology came along to replace copper telephone lines, existing ducting infrastructure would make the job a heck of a lot easier. And like in the real world, if you don't think ahead, rectification could either be costly or impossible.