Archive for the ‘Tech’ Category

Step by step: creating a virtual machine on a headless server

The following instructions may give you an idea how to create a virtual machine on a headless server over a network connection. We will create a virtual machine, establish an RDP connection and install a guest operating system — all without having to touch the headless server. All you need is the following:

  1. VirtualBox on a server machine with a supported host operating system. The VirtualBox extension pack for the VRDP server must be installed (see the previous section). For the following example, we will assume a Linux server.
  2. An ISO file accessible from the server, containing the installation data for the guest operating system to install (we will assume Windows XP in the following example).
  3. A terminal connection to that host through which you can access a command line (e.g. via ssh).
  4. An RDP viewer on the remote client; see Section 7.1.1, “Common third-party RDP viewers” above for examples.

Note again that on the server machine, since we will only use the headless server, neither Qt nor SDL nor the X Window system will be needed.

  1. On the headless server, create a new virtual machine:
    VBoxManage createvm --name "Windows XP" --ostype WindowsXP --register

    Note that if you do not specify --register, you will have to manually use the registervm command later.

    Note further that you do not need to specify --ostype, but doing so selects some sane default values for certain VM parameters, for example the RAM size and the type of the virtual network device. To get a complete list of supported operating systems you can use

    VBoxManage list ostypes
  2. Make sure the settings for this VM are appropriate for the guest operating system that we will install. For example:
    VBoxManage modifyvm "Windows XP" --memory 256 --acpi on --boot1 dvd --nic1 nat
  3. Create a virtual hard disk for the VM (in this case, 10GB in size):
    VBoxManage createhd --filename "WinXP.vdi" --size 10000
  4. Add an IDE Controller to the new VM:
    VBoxManage storagectl "Windows XP" --name "IDE Controller"
          --add ide --controller PIIX4
  5. Set the VDI file created above as the first virtual hard disk of the new VM:
    VBoxManage storageattach "Windows XP" --storagectl "IDE Controller"
          --port 0 --device 0 --type hdd --medium "WinXP.vdi"
  6. Attach the ISO file that contains the operating system installation that you want to install later to the virtual machine, so the machine can boot from it:
    VBoxManage storageattach "Windows XP" --storagectl "IDE Controller"
          --port 0 --device 1 --type dvddrive --medium /full/path/to/iso.iso
  7. Start the virtual machine using VBoxHeadless:
    VBoxHeadless --startvm "Windows XP"

    If everything worked, you should see a copyright notice. If, instead, you are returned to the command line, then something went wrong.

  8. On the client machine, fire up the RDP viewer and try to connect to the server (see Section 7.1.1, “Common third-party RDP viewers” above for how to use various common RDP viewers).

    You should now be seeing the installation routine of your guest operating system remotely in the RDP viewer.

When you feel it’s enough repeating same errors at the same place, you will try to learn from those lessons, trying to figure some rules to follow, which enable you to avoid those mistake from happening again. That’s how “Best Practice” comes. There are so many books about them. For some experienced programmers, they try not to make those mistakes even for once. But there are still some who would argue with you. When you try to convince them not to hard code, they say they can finish the job faster. It’s hard to make your case since they do finish the job in less time.

So I think we should have some sort of course or workshop. We deliberately arrange some scenarios in which programmers would violate those best practice. And let them go through the pain themselves. That might help them understand the importance of best practice, converting the reading experience into a personal one.

Sys

The last project I worked on got a lot of cache penetratraion on the first online day. All this happened again, though I was not in first line of development this time. Well, we just shouldn’t expect a perfect opening without any downtime, not if we have not spent enough resource to ensure the system quality, from the availability, performance and functionality view.

It’s highly temptating to be slack on test and fulfill more functionality. We try only one or two path, making some optimistic assumtions. If everything is OK, we assume the test is finished. And we rarely do rehearsal on disaster recovery. When disaster does happen, the measure we applied before would just don’t work.

And there is the simplicity problem. We are so easy to get ourself to a complicated architecture, only because we think it is totally under our control at the time, while it’s not after the complixity builds up and some emergency happens.

Book extract: Mobile Application Context:

Table 6-2. Application context matrix
User experience type Task type Task duration Combine with
Utility At-a-glance Information recall Very short Immersive
Locale Location-based Contextual information Quick Immersive
Informative Content-based Seek information Quick Locale
Productivity Task-based Content management Long Utility
Immersive Full screen Entertainment Long Utility, locale
As

Extract from book – “Mobile Design and Development”:

• Don’t trust any report, fact, or figure that is more than a year or two old. It is most likely wrong. For example, the majority of assumptions about mobile development pre-iPhone are no longer applicable.

• Perform contextual inquiries, not focus groups. Go to your users and ask them questions in person, in their context, not yours. They often have a lot to say; listen and keep an open mind.

• Record everything. Nothing makes your case like your users’ own words. They have a funny way of reducing company politics and focusing back on the user.

• Don’t forget to innovate. Try new things, be bold, and don’t be afraid to fail.

• The best strategy succeeds even if it fails. Have a contingency plan. If your plan fails to meet expectations, how can you reuse what you’ve learned or done on something else?

Both of them are luxuries to me. I’ve heard of them hundreds of times, from Leo’s talk show as well as many tweets. But they are still far away from my laptop screen.

I did try to enable the Google Instant Search. I used a proxy, located in Las Vegas, changed my locale settting to en_US, and changed all those setting trying to tell Google I was in America. But the google was very smart, the regional setting awlays bounced back when I did some more clicks. The worse part was, the Instant Search will be disabled automatically when it detects my connection speed is too slow. Well, it can’t be fast when I’m using a cheap proxy.

The new twitter.com UI simply doesn’t show up yet. One of my colleagues got it today. How unfair it is! He is an inactive user, with only less than 10 followers, And his tweets are all private!

After the long and frustrating bug tracing of my android program, I think I’ve some idea about how sqlite and android control the version of its database schema.

At first, I guessed the version number is table-basis, i.e. you specify a version number for each table, and the android program will check the version number to decide whether this table needs to be altered. I was wrong. The android program use the Pragma, user_version, to do the version tracking. Since the db is exclusive to each android app, so this parameter is used to reflect the db schema version of each app.

Let’s see the whole process. When the SqliteOpenHelper class creates the table, it receives a version value and set it to the pragma “user_version”. Next time it receives another version number, it checks it with the existing version, which is retreived from that pragma. If the existing version is lower, it will call the appropriate method to alter the table, then update the existing version. So when any table wants to change its schema, it needs to specify a version number higher than the current one.

That’s pretty straightford, huh? It is until we need to modify multiple tables. Of course it depends on the approach we use to upgrade our db schemas. In my case, I create a helper class for each table. So if I wants to upgrade two tables and provide the same version number for both of them, the first one got upgraded will set the version number after the finish of upgrade. That’ll prohibit the 2nd table from upgrading, since the two version number are equivalent now.

When the Chinese government blocked foursquare.com, I downloaded a tiny zip file, in which there were only a handful of php and apache config files. It made my 4sq app on android cellphone work again. I skimmed through the source code. It’s pretty simple, just a comple lines to implement the request redirect function.

I found my Twip proxy for Twitter didn’t work anymore. It’s already the latest version. I looked like there was little I could do. And suddennly the 4sq proxy came to my mind. Hey, maybe I could modify it and use it for twitter.

And it did work. All I needed to do is just change the value of the api url to twitter’s url, and config a subdomain for it. It worked breezily!

Here is the source code of the two main important files:

1. .htaccess (the apache config file which lets 4sq.php process all the request):

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . 4sq.php [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
</IfModule>

2. 4sq.php (grabs the request, and redirects them to the real receiver):

<?php
$file_name = ’4sq.php’;
$api_root = ‘http://api.twitter.com/’;
$request_uri = $_SERVER['REQUEST_URI'];
$pos = strpos($_SERVER['SCRIPT_NAME'], $file_name);
$path_component = substr($_SERVER['REQUEST_URI'], $pos);
$curl = curl_init();
$headers[] = ‘Connection: Keep-Alive’;
$headers[] = ‘User-Agent: FxxkGFW’;
$username = $_SERVER['PHP_AUTH_USER'];
$password = $_SERVER['PHP_AUTH_PW'];
curl_setopt_array($curl, array(
CURLOPT_URL => $api_root . $path_component,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_USERPWD => “$username:$password”)
);
if ($_SERVER['REQUEST_METHOD'] == ‘POST’) {
curl_setopt_array($curl, array(
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => @file_get_contents(‘php://input’)
));
}
$result = curl_exec($curl);
curl_close($curl);
?>

Pretty old post, but still worth jotting down:

  1. Don’t reinvent the wheel.
  2. Use open source.
  3. Automate everything.
  4. Design for scale – plan to be lazy from the start.
  5. Design for hardware manageability.
  6. Use good cluster management software – don’t dig wells with teaspoons.
  7. Use open source monitoring solutions.
  8. Control your users with a queuing system.
  9. Verify you get what you pay for – benchmark it!
  10. Manage cluster communication.
  11. Look for ways to become lazier.

Source

I’ve released my new Greasemonkey Script, ClassicRetweetFor163Weibo, today. It took me two days to finish the first version, starting from last noon.

I barely remembered the tricks of GM, so I had to read the book again, partially. The developer of 163weibo uses very complicated javascript library, which injects event to DOM elements. It’s difficult to find those snippets deserve my attntion. But anyway I did it.

And on Sean’s demand, I improved it a little bit. Now it uses the standard opost input box to retweet. ^_^