Saturday, November 19, 2005

Building a virtualized Team Foundation Server development environment

Given the recent RTM release of Visual Studio 2005 and all the hype around Team Foundation Server, I wanted to build a development environment where I could play with both. So, I finally managed to do it using Virtual PC. I thought I’d share the knowledge of what took me several hours (days, rather) to complete.

My goal was to virtualize a development environment that contained a TFS server and one or more clients. I’d heard that one needed to install TFS within an Active Directory domain. However, after reading the install documentation, I found that to only be necessary if the data tier (SQL Server 2005) and the application tier (TFS) were to be run on separate machines; this is what the doc calls a Dual-Server Deployment. On the contrary, if both the data and application tiers are installed on the same machine (Single-Server Deployment), a domain is optional.

But since many development shops will have Active Directory running, I wanted to simulate it. So, one option would be to install all of TFS on a single machine that was also a Domain Controller. However, it is also common knowledge that installing TFS on the Domain Controller itself is problematic (at least it has been with previous TFS betas). Given all that, I decided to build three virtual machines:
  • A stand-alone Domain Controller – 256 MB RAM
  • The “TFS server” with SQL Server 2005, Windows Sharepoint Services SP2 (another prereq for TFS), and Team Foundation Server itself – 512 MB RAM
  • A client machine with a Team Edition of Visual Studio 2005 installed (in my case, I have access to a licensed copy of Team Edition for Software Developers) – 512 MB RAM
The total RAM requirement was 1.5 GB, which fit my memory budget since my host OS (Windows XP Pro on a Dell Latitude D600 laptop) has 2 GB.

To build all of this, I needed the following software “ingredients”:
  • A base VM image of Windows Server 2003 that had been Sysprep’d. Make sure this image either has a local copy of the Windows Server 2003 install CD’s I386 directory or you have the CD or an ISO handy. I’m going to use this base image for all three machines, even the client. However, one could just as easily build the client with Windows XP
  • A handy copy of the Team Foundation Server install documentation (TFSInstall.chm), which can be found on the CD/ISO
  • A SQL Server 2005 install CD/DVD or ISO (Standard or better). In my case I had Developer Edition
  • The install for Windows SharePoint Services 2.0 with SP2, which can be downloaded here
  • The Team Foundation Server, Beta 3 Refresh CD or ISO
  • A Microsoft Office 2003 CD or ISO that contains both Word and Excel.
  • The Microsoft Project 2003 Professional CD or ISO
  • A Team Edition Visual Studio 2005 install DVD or ISO
And, finally, here is the list of steps I took to cook it all up:

Build the Domain Controller VM
The domain controller will host a private Active Directory domain. As a bonus, it will also act as a gateway router to the outside world. If any of the machines in the local virtual network require outside (i.e. internet) access, the 2nd network adapter on this machine can be bound to a physical network interface on the host machine, and Routing and Remote Access will provide NAT access to the outside. This capability will actually be called upon when we build the client VM later in this post.
  1. Create a new VM by copying the base Windows Server 2003 VM files.
  2. In the VM Settings, set the memory to 256 MB.
  3. Change the network adapter to Local only.
  4. Add a second network adapter and bind it to one of the host OS’s network adapters.
  5. Start the VM and let it run through all of the initial Sysprep setup stuff.
  6. Log in as the local administrator.
  7. Change the guest OS network connection bound to Network Adapter 1 so that it has a static IP address. I went with these settings:

    IP: 192.168.100.1
    Subnet Mask: 255.255.255.0
    Default Gateway: 127.0.0.1

  8. Change the VM’s computer name to something meaningful. I went with W2k3TFSB3R-DC. A side note: computer names should be limited to 15 characters or less since that’s the max length of a NetBios computer name.
  9. Run the Configure Your Server Wizard (Administrative Tools). The wizard will automatically suggest that you make the server a domain controller, a DNS server, and a DHCP server. And, since you have two network adapters, it will also suggest installing Routing and Remote Access. Do all of this. I chose to use tfs.local as the Active Directory domain name. This will require a reboot.
  10. In the VM Settings, change the binding of Network Adapter 2 to Not connected. This will keep the network of VM’s completely isolated from the outside world. If you need to connect them for any reason, you can always reconnect the adapter to a physical adapter.
  11. Create the following domain accounts and allow them to remain in their default security group (Domain Users):

    TFSSETUP – This will be used when running TFS setup on the TFS server and will also automatically be joined to the TFS Administrators Application Group
    TFSSERVICE – Used as the identity for TFS Windows services
    TFSREPORTS – Used by SQL Server Reporting Services
    TeamDeveloper – User account of the developer on the client machine

  12. Leave this VM running.

Build the TFS Server VM
The TFS server will host all of the Team Foundation Server server-side components (application tier) as well as the supporting database (data tier). It will also host Team Foundation Build, which enables automated builds. The kicker is that in order to perform testing and code analysis in the build, a Visual Studio Team SKU needs to also be installed on the server. Luckily, VS Team licensing is per-user, and not per-machine, so installing VS on the server won't break the budget. In our case, we will be installing the same VS SKU on the server as the client machine.

  1. Create a new VM by copying the base Windows Server 2003 VM files.
  2. In the VM Settings, set the memory to 512 MB.
  3. Change the network adapter to Local only.
  4. Log in as the local administrator.
  5. Change the VM’s computer name to something meaningful. I went with W2k3TFSB3R-SVR. And while you’re doing this, join the computer to the tfs.local domain. This will require a reboot.
  6. Log in as the domain administrator (TFS\Administrator) instead of the local administrator.
  7. Add the TFSSETUP domain account to the local Administrators security group.
  8. Run the Configure Your Server Wizard and turn on the Application Server role, which will enable IIS (make sure to allow ASP.NET).
  9. Install your copy of Visual Studio 2005. You really only need to install the bare minimum since this VS install is solely there to support Team Foundation Build. Therefore, the only components necessary are the following:

    Microsoft Visual Studio 2005 Team Edition >
    Team System {your SKU} Tools >
    - Code Analysis Tools
    - Testing Tools

    where {your SKU} is the version of Visual Studio Team Edition that you have (in my case, I have Team Developer).

    And of couse, you don't need to install MSDN.

  10. Install SQL Server 2005 using the instructions found here in the TFSInstall.chm file:

    Overview of Team Foundation Server Single-Server Deployment >
    Installing Team Foundation Server >
    How to: Install Microsoft SQL Server 2005 for Team Foundation Server (Single-Server Deployment)

    NOTE:
    I would advise using the TFSQL2005AnswerFile.ini answer file approach, which is explained at the bottom of the doc page under the section: To install Microsoft SQL Server 2005 using an answer file.

  11. Install Windows SharePoint Services 2.0 with SP2 using the instructions here in the TFSInstall.chm file:

    Overview of Team Foundation Server Single-Server Deployment >
    Installing Team Foundation Server >
    How to: Install Microsoft Windows SharePoint Services for Team Foundation Server (Single-Server Deployment)

  12. Log off and log back in as TFS\TFSSETUP.
  13. Install Team Foundation Server using the instructions here in the TFSInstall.chm file:

    Overview of Team Foundation Server Single-Server Deployment >
    Installing Team Foundation Server >
    How to: Install Team Foundation Server

  14. Install Team Foundation Build using the instructions here in the TFSInstall.chm file:

    Overview of Installing Team Foundation Build >
    How to: Install Team Foundation Build

  15. Leave this VM running.

Build the TFS Client VM

The TFS client will contain all client-side development tools as well as the client-side software for accessing Team Foundation Server, which is called Team Explorer. Team Explorer is not its own application, but rather a set of add-ins that integrate seemlessly with Visual Studio 2005. The TFS client machine will also host a local instance of SQL Server 2005 as well as all of the SQL Server developement tools that come along for the ride.

  1. Create a new VM by copying the base Windows Server 2003 VM files.
  2. In the VM Settings, set the memory to 512 MB.
  3. Change the network adapter to Local only.
  4. Log in as the local administrator.
  5. Change the VM’s computer name to something meaningful. I went with W2k3TFSB3R-C-TD. And while you’re doing this, join the computer to the tfs.local domain. This will require a reboot.
  6. Log in as the domain administrator (TFS\Administrator) instead of the local administrator.
  7. Add the TeamDeveloper and TFSSETUP domain accounts to the local Administrators security group.
  8. Log off and log back in as TFS\TeamDeveloper.
  9. Install Microsoft Office 2003 from your Office CD/ISO. At a minimum you need to install Word and Excel (complete installs of each). This is a prerequisit for the upcoming Team Explorer install.
  10. Install Microsoft Project 2003 Professional (complete install) from your Project CD/ISO. This is a prerequisit for the upcoming Team Explorer install.
  11. On the domain controller VM (W2k3TFSB3R-DC), bind the Network Adapter 2 to one of your physical network adapters. This should allow all the VM’s access to your physical network (and presumably the internet) via Routing and Remote Access. If this doesn’t work, you can always set the Network Adapter of the TFS Client from Local only to one your physical network adapters.
  12. Perform a Microsoft Office Update.
  13. On the domain controller VM (W2k3TFSB3R-DC), set the Network Adapter 2 back to Local only.
  14. Install your copy of Visual Studio 2005. Make sure you specify to install SQL Server Express. We’re going to also install the full version of SQL Server 2005 in the following steps. However, there are advantages to having both installed; one of them being many of the sample apps that come with Visual Studio only seem to work with Express.
  15. Install the MSDN Documentation that comes with Visual Studio 2005.
  16. Install SQL Server 2005. I have the Developer Edition and chose to install the following components:

    - SQL Server Database Services
    - Reporting Services
    - Integration Services
    - Client Tools, Books Online

    You may be prompted that some of the components are already installed (since we installed SQL Server Express earlier via Visual Studio). Make sure to re-check any components that it asks for at this point.

  17. Install Team Explorer using the instructions here in the TFSInstall.chm file:

    Overview of Installing Team Explorer >
    How to: Install Team Explorer

  18. Open Visual Studio 2005 and connect Team Explorer to the server (W2k3TFSB3R-SVR) using the instructions here in the TFSInstall.chm file:

    Overview of Installing Team Explorer >
    How to: Connect Team Explorer to Team Foundation Server

That’s it! ;-)

Now you’ve got a handy virtualized Team Foundation Server development environment, complete with the build server (Team Foundation Build) that you can use to play around with, demo, and even develop real code using TFS.

Good luck!

Thursday, May 05, 2005

Version Tolerant Serialization

Sorry, I haven't posted anything to my blog in a while (not that anyone was holding their breath... well, except for maybe Jason :-) )...

I've done a thing or two with .NET Serialization and Remoting in the past and presently I'm doing some stuff where we're considering all of the transport options that come with .NET: Remoting, Web Services, Enterprise Services, and the soon-to-be new kid on the block, Indigo. Recently, I watched an MSDN TV show with Matt Tavis on the new features added to Remoting coming up in .NET 2.0. I think its great that their expanding the functionality of Remoting (especially since many were claiming that it was dead back when Indigo was first announced). The reality is that they're adding some really cool features. At a high level they are:
  • A new channel called the IPC Channel which is optimized for same-machine inter-process Remoting. It uses named pipes instead of TCP/IP for communication.
  • An option to secure the TCP Channel using SSPI-based security that is offered in the new System.Net.Security namespace.
  • Socket cache control
  • Generics support
  • IPv6 support
  • Version tolerant serialization
That last feature is the one I'd like to comment on. Technically this new feature isn't specific to Remoting, but is a part of .NET Serialization, which is broader technology used by Remoting.

VTS and Remoting
In .NET 1.x if you serialized an object of a given type and then deserialized using a newer version of that type and the new type had additional (or removed) fields, you would get seriaization errors. The only work around was to implement the ISerializable interface. However, this approach was crude as you were responsible for reading and writing directly to the serialization stream and things got worse when you wanted to serialize an object hierarchy. Microsoft's answer to this issue is Version Tolerance Serialization. VTS essentially adds 5 new attributes to the System.Runtime.Serialization namespace that allow you to mark fields as optional (these would be used with the new fields on the new type) as well as mark methods in your class for handling specific events in the serialization/deserialization process. In a Remoting scenario, what this lets you do is update a type on the server-side to a new version and let the client-side versions remain the same, without throwing serialization errors.

Now, in and of itself, this is pretty cool. But I think its worth it to take a moment to offer up a word of caution. There's a reason why the original serialization mechanism was version intolerant (and it wasn't just because the Microsoft developers were too lazy to add tolerance support). If the object you're serializating across the wire is nothing more than data, then this new feature is fairly safe. But if you're actually remoting objects that are more object-oriented (both data and logic together) then caution needs to exercised. While VTS may prevent serialization (i.e. schema) errors from occurring, it won't stop differences in logic between the two type versions from totally hosing up your application. In other words, when you code up version 2 of the serializable object, you better be thinking about version 1, version 1.5, and any other version between what the client was compiled against and what you've got sitting in your IDE. The question to ask when considering this new feature is this: is it more work to force clients to always get the latest binaries or to add backward-compatibility support to my new type? I think in many cases it's more complex to do the later. Especially when you consider many of tools we have today that allow client applications to automatically update their binaries.

So, in a Remoting scenario where you allow the client and server to version independently I think one needs to exercise caution (and a lot of good unit testing) before hailing this feature as the answer to all our versioning problems. Throwing a new version of a type onto a server with minimal effort to support backward compatibility will lead to a lot of very hard to debug application errors and may even lead to bad data getting persisted to the database. Rocky Lhotka talks more about this problem is a more generic scense in this article on TheServerSide.net.

Howerver...

VTS in General
I think there is a scenario where this new feature shines without the aforementioned caviat. I was on a project once where we used serialization to persist objects to disk instead of persisting them to a traditional RDBMS. The application was a desktop app similar to Microsoft Word where the user worked with "documents" and could save and load them as files. It seemed like a natural fit to have the document be some kind of object model that was persisted to and from disk via serialization. Everything worked fine until we started thinking about version 2 of our app. While there were ways to relax the versioning restrictions in in .NET 1.x serialization when the schema didn't change, the moment we added new fields to our types, the fated serialization errors occurred.

But this scenario was different than Remoting in that we only had to worry about the difference in type data (schema), not logic. This is because we were not interoperating with the older type. We just had to figure out a way to transform data serialized by an old type so that it would fit the schema of a new type. In the end, we ended up writing an elaborate upgrade system that would parse the serialized data itself (which in our case was SOAP XML) and transform it to a newer version, adding fields as necessary. This was not an ideal solution. First, it was very complex. Second, it essentially broke the rule of encapsulation, since the upgrader tool had to have intimate knowledge of the fields of the type is was upgrading. It would have been better to place the responsibility of managing new fields of a type within the type itself. I believe the new VTS features of .NET 2.0 allow us to do just that and with minimal effort.

Tuesday, April 05, 2005

Clearscreen CAPTCHA Control now supports CS 1.0!

Wow, that didn't take long. Miguel Jiménez has updated his CAPTCHA control to version 1.4 and it now works with Community Server! And here I was all set to hack the source code myself so I could get something up and running. Oh well, I've got better things to do with my time anyway. ;-)

And the good news is that it actually works! Check it out; it's running on my site.

Monday, March 28, 2005

Evolution and creation in the classroom

Check out this interesting discussion on a recent news article talking about a possible Florida mandate to force equal time in the college science classroom for both evolution and creation.

Feel free to chime in; unlike my (insert adjective here) blog engine, Jason's accepts anonymous comments.

Wednesday, March 23, 2005

Community Server and CAPTCHA

So far I've been pretty thrilled with Community Server as my blog engine. One of the things I didn't set up right away was anonymous comments for my blog entries. I wasn't sure how CS would handle spam comments, so I left it disabled for the time being. Well, after doing some research this evening I found a few things about controlling spam comments in a blog and, specifically, in CS:
  1. The most popular deterrent is to implement a CAPTCHA control.
  2. A very popular CAPTCHA implementation for ASP.NET is Miguel Jimenez's Clearscreen SharpHIP HIP-CAPTCHA Control.
  3. The Clearscreen SharpHIP HIP-CAPTCHA Control was specifically designed with the .Text blog engine in mind, the predecessor to Community Server. However, it can be used with any traditional ASP.NET web form.
  4. And, one more minor thing: the Clearscreen SharpHIP HIP-CAPTCHA Control doesn't work with Community Server.
    Rats.

Community Server does some pretty funky stuff with the request URLs, which, I'm sure is what's hosing up the control. Anyway, I'm going to keep an eye on Miguel's blog to see if he posts an update that's compatible with Community Server.

If anyone else out there has a better solution (besides using a different blog engine), please let me know. Of course, you're going to have to log in to my CS site in order to leave that comment. Oh, the irony.