March 6, 2010, 1:01 pm
After many months of hard work, our new service Mammoth VPS was launched this week. The service is a good fit for us I think, making use of the many years of experience we’ve had managing servers at Telstra; but being virtualized requiring relatively little physical hands-on work at the data centre.
It was also an interesting project from a development point of view, figuring out how to automate all the various Xen related tasks. We have also taken the presumedly un-usual route of running the load-balanced ASP.NET web application on both Windows and Linux. This required partially reimplementing the built-in FormsAuthentication class (which behaves differently in Mono) to allow the session cookie to be readable on both platforms, but otherwise is performing well. The website’s load times are really snappy, so I’m happy in that regard.
January 25, 2010, 8:51 am
Now I can put my DVD’s away and watch them with XBMC instead:
dvdbackup -Mo /tmp/rip && mkisofs -dvd-video -o /mnt/storage/Movies/newmovie.iso /tmp/rip/* && rm -rf /tmp/rip
December 27, 2009, 7:49 am
I took the plunge today and reinstalled Ubuntu from scratch. I thought it might be interesting to see what additional software I had to install:
- NVidia driver + this xorg.conf fix
- Packages vim and vim-gnome
- Dropbox (from www.getdropbox.com )
- Package nfs-common to access storage on my home NAS
- Package smbfs to mount Windows shares at the command line (I find this preferable to the smb://server IO-helpers that Gnome and KDE have)
- Package xchat-gnome for access to Mammoth’s IRC server
- Package msttcorefonts for the freely available Windows fonts include Arial for compatibility with websites that assume everyone has Arial.
- Thunderbird 3.0 from the Mozilla Daily PPA
- Package screenlets – specifically, the Sidebar (with ‘Dock other screenlets’ disabled), three RingSensors, ClearCalendar, ClearWeather, Clock, and Slideshow screenlets all configured to ‘Stick to Desktop’.
- The 64-bit Flash beta in Package flashplugin64-installer from this PPA
- Package qmmp is a very basic MP3 player, similar to the old Winamp releases
- Firefox plugins: Greasemonkey, Net Usage Item
- Package virtualbox-ose for VirtualBox.
- Package apache2 for development/testing.
- Package meld is a great visual diff tool.
I will keep this updated over the next few weeks.
December 26, 2009, 12:59 pm
The Ubuntu Live CD does not come with LVM or the MD administration tools, so if your existing system uses LVM and/or MD (the linux software RAID functionality), the partitions are not visible by default within the LiveCD. To get access to your data, pull up a terminal (Applications menu → Accessories → Terminal) and switch to root:
ubuntu@ubuntu:~$ sudo -i
root@ubuntu:~#
Start by installing the software needed (since its a live CD, this just installs to the temporary in-memory “RAM disk”):
root@ubuntu:~# apt-get install lvm2 mdadm
With that completed, you can assemble your existing array(s):
root@ubuntu:~# mdadm --assemble --scan
mdadm: /dev/md0 has been started with 2 drives.
Then scan for the LVM physical volumes:
root@ubuntu:~# pvscan
PV /dev/md1 VG nathan lvm2 [465.52 GB / 0 free]
Total: 1 [465.52 GB] / in use: 1 [465.52 GB] / in no VG: 0 [0 ]
Activate the logical volumes contained within:
root@ubuntu:~# vgchange -a y
3 logical volume(s) in volume group "nathan" now active
And finally, mount whichever partition you were interested in:
root@ubuntu:~# mount /dev/nathan/data /mnt
December 1, 2009, 4:29 pm
My latest in a very occasional series of articles was posted on AusGamers a few weeks back, detailing how to build a cheap HTPC with Ubuntu and XBMC. In the comments there was of course, the usual resistance to using Linux - despite the simplicity of the guide.
December 1, 2009, 4:19 pm
Last week I had to build an unattend.xml script that among other things, set the system up with a static IP. This seems easy enough but I just couldnt get it to work until I found this blog post.
Yes, the position of <identifier> in respect to its sibling elements matters. I never would have thought of that in a million years, so much praise to Renaud Depagne !
September 23, 2009, 5:39 pm
Today I was making sure that GZIP and the HTTP Expires header was enabled on all the content of our new ASP.NET MVC application. We have a little bit of code in our Global.asax to set up compression and expires appropriately.
I was surprised to find that despite using wildcard-mapping and IIS6 (which would result in all HTTP requests being ‘visible’ to Global.asax in a regular WebForms application), that our stylesheets were no longer being setup correctly.
Fiddling with the HTTP Header Expires setting in IIS confirmed that the stylesheet file appeared to be processed directly by IIS, which I had previously thought was impossible when using wildcard + IIS6.
I also found it strange that an MVC application would differ compared to WebForms: my understanding was that the new System.Web.UrlRoutingModule simply passed on-disk files to the appropriate handler, in this case System.Web.StaticFileHandler.
However, with a bit of testing I found this was not the case: modifying the web.config with:
<system.web>
<httpHandlers><add verb="*" path="*.css" type="System.Web.StaticFileHandler"/></httpHandlers>
</system.web>
Resulted in the Global.asax processing the request. This blog post mentions the potential behaviour of System.Web.DefaultHttpHandler in terms of passing files back to IIS (though its not mentioned where or how this was learned), and indeed this does appear to be exactly the case in MVC.
Poking through System.Web.DefaultHttpHandler in Reflector its not clear to me how this actually works, but its clear from my testing that a typical MVC application will have its static on-disk files sent directly by IIS.
July 10, 2009, 6:18 am
This was the first relevant hit I received from Google, which mentions the handy fact that there’s an alternate key combination for the same effect: Alt+PrintScreen+K. Wikipedia has a nice list of the available system requests on linux, including the handy by verbose “REISUB” sequence for rebooting a frozen machine.
July 9, 2009, 9:18 am
Jared sent me this blog post which I found quite interesting. The article itself I feel is worded kind of poorly, even right from the title (I dont think anyone really argues about data access any more) but the core concept of “how much engineering is too much?” is discussed with more riguer in the comments.
As an employer who is both supportive and encouraging of the ALT.NET patterns and processes (though there’s little agreement on exactly what those are), I have my own perspective on this issue. While it can sometimes be tempting to think about good software development principles in a vacuum, its also important as developers to remember why we are employed: to build software.
As an employee, we are a cost (the input) that is subtracted from the revenue our employer gains from the software we make (the output). Since for most employees their salary does not vary according to output, the most valuable employees are those that create the most software per unit of time. However, many of us have rightfully rallied against RAD tools as creating unmaintainable solutions that are hard to alter as requirements change.
If you want to be a valuable employee (and chances are you do, since a valuable employee is a well-paid employee) it is still your primary responsible to figure out how you can develop as much software as you can per unit of time. There are really three parts to this:
- Time to market: how long does it take to get the each version ready for deployment, given a predictable incremental approach to requirements?
- Defect rate: defects have two costs: the time to fix them, and the negative impact they have on customer satisfaction.
- Malleability: how long does it take to get successive versions ready for deployment as requirements change?
RAD tools focus too heavily on the first criteria while ignoring the others. Over-engineering focuses too much on the third criteria while ignoring the first one. Conery summarises this as “Simplicity is beautiful”; the best developers will adapt an approach that satisfies all three criteria.
June 20, 2009, 7:56 am
Yesterday I had a solution where I wanted to receive a domain entity as an action parameter, similar in concept to the built-in ActiveRecord data-binding. In my situation though I wanted to use a slug to identify the entity. My URL’s look like this:
/news/slug-goes-here
which I want to result in calling into:
public class NewsController
{
public void Index(NewsItem item)
{
}
}
The first step here is to setup routing to suit. We currently just use an XML file to hold our routing rules, so this route entry just looks like
<rule>
<pattern>^/news/([^/]+)$</pattern>
<replace>/news/index?item=$1</replace>
</rule>
With this in place, our Index action will receive item as an argument. All that’s left to do is tell MonoRail how to bind the item argument to our NewsItem type. There are two approaches available here: you can derive a class From DataBinder and pass it to the SmartDispatchController contructor, or you can create a new attribute that implements IParameterBinder and attach it to the action’s parameter. Unfortunately in MonoRail 1.0 the DataBinder class from what I can tell is really only extensible via inheritance, so I have used the attribute approach.
MonoRail’s source is a real help here, since you can inspect DataBindAttribute.cs to see what the class should be doing. Here is the implementation I ended up with:
public class NewsItemAttribute : Attribute, IParameterBinder
{
public int CalculateParamPoints(SmartDispatcherController controller, ParameterInfo parameterInfo)
{
CompositeNode node = controller.ObtainParamsNode(From);
IDataBinder binder = CreateBinder();
return binder.CanBindObject(typeof(string), prefix, node) ? 10 : 0;
}
public object Bind(SmartDispatcherController controller, ParameterInfo parameterInfo)
{
IDataBinder binder = CreateBinder();
ConfigureValidator(controller, binder);
CompositeNode node = controller.ObtainParamsNode(From);
var slug = (string) binder.BindObject(typeof(string), prefix, exclude, allow, node);
var instance = IoC.Resolve<INewsItemRepository>().GetBySlug(slug);
BindInstanceErrors(controller, binder, instance);
PopulateValidatorErrorSummary(controller, binder, instance);
return instance;
}
}
The only line of note here is the IoC.Resolve() call. To my knowledge you cant use DI with attributes, so we’re stuck with using the service locator approach. The rest of the code is straight from the DataBindAttribute source.
I’ve not yet gotten the chance to use ASP.NET MVC in a project, but from what I’ve read the ModelBinder facility appears a much cleaner approach to this problem than that possible with MonoRail 1.0.