Thursday, November 08, 2007

Synchronizing AD with TFS

Just today I had the extremely frustrating task of forcing a synchronization between AD and TFS. The background of the problem was the inclusion of a user in an Active Directory group. The AD group was already associated with a TFS permission group.

After looking around on the net for a while, I came across this forum thread:
http://forums.microsoft.com/MSDN/showpost.aspx?postid=1403304&siteid=1

I invoked the web service to return the last time the ACL synchronization occurred and was a bit surprised to see that it was actually a lot longer than 1 hour ago. From what I read, if the web.config setting was not explicitly declared, it would default to 1 hour.

What I had to do was create a new TFS group, associated an Active Directory group with it, then delete the TFS group.

It's not a very elegant solution but there are many times where you must force the synchronization due to support requirements. I'm not impressed that no TFS web service exists to manually invoke the synchronization.

Sunday, November 04, 2007

TFS Custom FTP Task to Mainframe

Recently, I've had the opportunity to build a custom task to FTP code from TFS to a mainframe environment. It was quite an adventure but ultimately rewarding when it finally succeeded. I adapted code that someone had kindly written to wrap the WinInet.dll and used it to FTP code to a mainframe running ZOS. I tested the custom FTP task on my FTP server in the windows environment and it worked like a charm.



All that remained was adapting it to the mainframe, or so I thought. My first few attempts were met with dismal failure. The error that got reported was: The server has returned an extended error. 200 Representation type is Ascii NonPrint.



After doing some research, I uncovered the fact that what we take as folders and files are instead known as datasets and members on the mainframe. Mainframe datasets are dot-separated as opposed to slash-separated in the Windows environment. Thus, a dataset would look like this:

MCP.STAGE1.COBOL



The fully qualified dataset and member would then look like this:

MCP.STAGE1.COBOL(MyFile)



It took me a while to understand that the file name could not accept an extension. Thus, I had to write a parsing algorithm to strip it out.



Once that was done, everything worked until the point where it failed because the dataset ran out of space. Another quirk I had to learn about was that the dataset had an allocated amount of storage. Once it ran out, it could not expand further. On another side note, another quirk I learned about datasets was that when they were not used for some time, they got archived to tape. This took a while to track down but we finally understood after one of the mainframe experts explained why the first time things ran, it failed and always succeeded on the second attempt.



Moral of the story: respect mainframes and be flexible with your mindset. Don't automatically treat everything in the same way as Windows or the more recent flavours or Unix/Linux.