Monthly Archives: November 2013

VirtualBox: Failed to delete the storage unit of the hard disk /PATH/HARD-DISK.vdi. Cannot close medium ‘/PATH/HARD-DISK.vdi’ because it has N child media.

After upgrading to VirtualBox 4.3.2 r90405, I get this dreaded error message when running VirtualBox:-

One or more virtual hard disks, CD/DVD or floppy disk image files are not 
currently accessible. As a result, you will not be able to operate virtual 
machines that use these files until they become accessible later.
Press Check to open the Virtual Media Manager window and see which files 
are inaccessible, or press Ignore to ignore this message.

I was able to clone the offending VDI and boot from the cloned VDI without losing any data. The cloning process took about half hour.

Now, when I try to remove the offending VDI under Virtual Media Manager, I get the following error message:-

Failed to delete the storage unit of the hard disk 
/Users/theUser/Library/VirtualBox/HardDisks/Windows.vdi.
Cannot close medium '/Users/theUser/Library/VirtualBox/HardDisks/Windows.vdi' 
because it has 2 child media.

So, I ran the following command on the Terminal:-

VBoxManage list hdds

… and these are the results I see:-

UUID:           8c688dc1-0ec3-4528-82b8-efd78a24277e
Parent UUID:    base
State:          created
Type:           normal (base)
Location:       /Users/theUser/Library/VirtualBox/HardDisks/Windows.vdi
Storage format: VDI
Capacity:       51200 MBytes

UUID:           7ef3723f-e960-4e68-9b8c-ef8d65b1474b
Parent UUID:    8c688dc1-0ec3-4528-82b8-efd78a24277e
State:          inaccessible
Type:           normal (differencing)
Location:       /Users/theUser/Library/VirtualBox/Machines/Windows 7 64/Snapshots/{7ef3723f-e960-4e68-9b8c-ef8d65b1474b}.vdi
Storage format: VDI
Capacity:       0 MBytes

UUID:           633a54a5-c3c0-4330-b371-9d448ae28c4c
Parent UUID:    8c688dc1-0ec3-4528-82b8-efd78a24277e
State:          inaccessible
Type:           normal (differencing)
Location:       /Users/theUser/Library/VirtualBox/Machines/Windows 7 64/Snapshots/{633a54a5-c3c0-4330-b371-9d448ae28c4c}.vdi
Storage format: VDI
Capacity:       0 MBytes

UUID:           7375877a-0e16-4803-a972-ac4e84f71a4b
Parent UUID:    base
State:          created
Type:           normal (base)
Location:       /Users/theUser/Library/VirtualBox/HardDisks/Ubuntu 32.vdi
Storage format: VDI
Capacity:       8192 MBytes

UUID:           70a8d322-a207-4e56-afc3-50fbaa97593e
Parent UUID:    base
State:          created
Type:           normal (base)
Location:       /Users/theUser/VirtualBox VMs/Ubuntu 64 Clone/Ubuntu 64 Clone.vdi
Storage format: VDI
Capacity:       10240 MBytes

UUID:           6d655fd9-362b-4ae6-b2ad-2be61582aa72
Parent UUID:    base
State:          created
Type:           normal (base)
Location:       /Users/theUser/VirtualBox VMs/Ubuntu 12.04 LTS - 64bit/Ubuntu 12.04 LTS - 64bit.vdi
Storage format: VDI
Capacity:       10240 MBytes

UUID:           1ff0ee93-bdf0-4162-ad50-636bbc8870cf
Parent UUID:    base
State:          created
Type:           normal (base)
Location:       /Users/theUser/VirtualBox VMs/Centos 64/Centos 64.vdi
Storage format: VDI
Capacity:       10240 MBytes

UUID:           190349ca-ce6d-4f95-bf65-f378f476c403
Parent UUID:    base
State:          created
Type:           normal (base)
Location:       /Users/theUser/VirtualBox VMs/Windows 7/Windows 7-disk1.vdi
Storage format: VDI
Capacity:       51200 MBytes

The highlighted rows are the offending VDIs that I tried to remove. After checking the file system, both Windows 7 snapshots no longer exist but VirtualBox still keeps track of them in VirtualBox.xml.

Using the UUIDs, I remove both snapshots first:-

VBoxManage closemedium disk 633a54a5-c3c0-4330-b371-9d448ae28c4c
VBoxManage closemedium disk 7ef3723f-e960-4e68-9b8c-ef8d65b1474b

Then, I remove the offending parent VDI:-

VBoxManage closemedium disk 8c688dc1-0ec3-4528-82b8-efd78a24277e

Now, when I rerun VirtualBox again, the error message does not appear anymore

Backbone: model.destroy() Always Call “error” Callback Function

PROBLEM

Let’s assume we invoke person.destroy() to delete a person:-

var person = Backbone.Model.extend( { ... } );

person.destroy( {
    contentType : 'application/json',

    success : function () {
        console.log('success');
    },

    error : function () {
        console.log('error');
    }
} );

… and let’s assume when person.destroy() is invoked, it will call /person/{personId} DELETE. Here’s how the Spring MVC controller API might look like:-

@Controller
public class PersonController {
    ...

    @RequestMapping(value = "/person/{personId}", method = RequestMethod.DELETE)
    public ResponseEntity delete(@PathVariable Long personId) {

        Person person = personService.getPerson(personId);

        if (person == null) {
            return new ResponseEntity<UnexpectedErrorBean>(new UnexpectedErrorBean("Invalid person ID"),
                                                           HttpStatus.BAD_REQUEST);
        }

        personService.remove(person);

        return new ResponseEntity(HttpStatus.OK);
    }
}

When we execute person.destroy(), the error callback function will always get called even though the HTTP status is a 200 OK.

Why?

SOLUTION

The reason is because Backbone expects a JSON payload from the web service call. In the example above, we return a 200 OK but without a JSON payload. Thus, Backbone will treat this as an error and invoke the error callback function instead of success callback function regardless of the HTTP status.

There are three solutions to this problem.

Solution 1: Add a JSON Payload

@Controller
public class PersonController {
    ...

    @RequestMapping(value = "/person/{personId}", method = RequestMethod.DELETE)
    public ResponseEntity delete(@PathVariable Long personId) {

        Person person = personService.getPerson(personId);

        if (person == null) {
            return new ResponseEntity<UnexpectedErrorBean>(new UnexpectedErrorBean("Invalid person ID"),
                                                           HttpStatus.BAD_REQUEST);
        }

        personService.remove(person);

        return new ResponseEntity<Long>(personId, HttpStatus.OK);
    }
}

In this approach, we add a JSON payload to satisfy Backbone. In the above example, we return the value of personId back to the client. It can be an empty object too.

I don’t like this approach because that piece of information is useless to the client side. Even if I return an empty object, the solution seems very brittle because the next team member inheriting my code will not understand why there’s a need to return an empty object back to the client.

Solution 2: Accept Payload as Text

var person = Backbone.Model.extend( { ... } );

person.destroy( {
    contentType : 'application/json',
		
    dataType : 'text',
		
    success : function () {
        console.log('success');
    },

    error : function () {
        console.log('error');
    }
} );

Another approach is to accept the data as text from the server. This solution works fine if we are not expecting any complex data structure back from the server.

Solution 3: Return a Different HTTP Status

@Controller
public class PersonController {
    ...

    @RequestMapping(value = "/person/{personId}", method = RequestMethod.DELETE)
    public ResponseEntity delete(@PathVariable Long personId) {

        Person person = personService.getPerson(personId);

        if (person == null) {
            return new ResponseEntity<UnexpectedErrorBean>(new UnexpectedErrorBean("Invalid person ID"),
                                                           HttpStatus.BAD_REQUEST);
        }

        personService.remove(person);

        return new ResponseEntity(HttpStatus.NO_CONTENT);
    }
}

The approach that I truly recommend is to return a 204 No Content instead of 200 OK. This way, the client side will not expect any payload from the server, and thus, Backbone will invoke the success callback function.

Homebrew: “Invalid Multibyte Escape” Error

PROBLEM

When running brew on OS X Maverick, you get this error:-

Error: /usr/local/Library/Homebrew/download_strategy.rb:84: invalid multibyte escape: /^\037\213/
invalid multibyte escape: /^\037\235/
Please report this bug: https://github.com/mxcl/homebrew/wiki/Checklist-before-filing-a-new-issue
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require'
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require'

SOLUTION

After upgrading to OS X Mavericks, the default version of Ruby is v2.0, causing Homebrew to break because it relies on v1.8. See issue #23655 for more information.

To fix this, run the following command:-

brew update

If you are getting the “Permission Denied” errors when running the above command, run the following command to fix the permission problem:-

# Assuming your user name is USER_HERO
sudo chown -R USER_HERO:admin /usr/local
cd /usr/local
git reset --hard origin/master
brew update