giving something back after taking a lot :-)

Maik Koster at myITforum.com

Extending the MDT Database with Custom Settings

February 16, 2009

The Settings within the MDT Database cover already a wide area of possibilities during a Deployment. But sooner or later you will probably reach a point, where you are in the need of adding or processing additional information. Think about Static IP Address assignment or prestaging a specific CollectionID for Deployment via SCCM, etc. There are probably a lot of things you might want to have. At least I reached this point quite soon during our deployments and started adding a new table for this and a new table for that and it was getting chaotic. Sure this is a way to secure your job but it could hit yourself if you try to understand or change this half a year later :-)

In this post, I would like to point out a more generic way how to add any kind of setting and explain how you can set and get these during your deployments.

One of the first guidelines which applies probably to everything which comes from somebody else: Don't change anything which might get updated in the future. So it's generally a bad idea to change any of the existing tables or views within your MDT Installation as you might run into problems on your next update. And even if I think the current Database design could have been done a bit different for easier consistency we will also stick to this schema.

So, one possible solution for this is a new table which will contain new settings, generic stored procedures, which will read and write any value, no matter what it contains and a view which will simply show all values. I will demonstrate this on a couple of custom settings I had to implement in our deployments. One requirement was the possibility to choose from a list of different deployment Task Sequences on-the-fly during Boot up but also being able to specify this in advance as a part of the prestaging process of computers. We solved this by simply adding two settings. One "CollectionID" which could contain a CollectionID (each OS Task Sequence is advertised to one Collection as mandatory) and a "Prestaged" value. If the CollectionID contains a value the Computer would be added automatically to the specified Collection. If not it would prompt a wizard where you then would get a list to choose from. And if the Prestaged Setting was set to YES we empty both Settings after the process. This was giving us the possibility to prestage a computer with a specific image without limiting future deployments, setting some computers fix to a specific image (e.g. Training computers) and still stay flexible enough to choose from a list if necessary (testing, etc). OK, enough wasted time on things you are not interested in :-) Let's get to the implementation.

First thing we need is a new table to store this information. We simply call this "CustomSettings" according to the Original "Settings" table. And while we are at it we also add a couple of views like "ComputerCustomSettings", "LocationCustomSettings", etc. Find an example sql script for this at the end of the post. I will skip the sql code for this as creating a table or view really doesn't look sexy.

However, we need an easy method to change/set and read these custom settings. And actually we have something similar already. You might remember the post about Set or Get a single Setting from MDT Database. We just take and change them accordingly and I hope you don't mind if I don't repeat this again. Find the necessary code attached. In the mentioned post I also showed how to create a webservice which could run this stored procedure. So this time we now concentrate a bit on how to use this (as the webservice for this CustomSettings is already part of the quite large webservice from my last post). I will do this with a simple example which you could use in the preexection hook. We want to check the MDT Database if a SCCM collection has been configured for the actual computer. If so, the computer shall be added to the collection. It's not a complete example. It will work but miss some parts like what do you want to do if no collection has been prestaged. So take it as a start for further testing.

What you need is a quite simple CustomSettings.ini

[Settings]
Priority= SetValues, ExecUserExit, AddToCollection
Properties=Type

[SetValues]
Type=Computer

[ExecUserExit]
UserExit=userExit.vbs

[GetMDTID]
WebService=
http://YourServer/DeploymentWebservice/mdt.asmx/GetComputerID
Parameters=SerialNumber, AssetTag, MacAddress, UUID

[GetCustomSetting]
WebService=
http://YourServer/DeploymentWebservice/mdt.asmx/GetCustomSetting
Parameters=MDTID, Type, Setting

[GetAssignedSite]
WebService=
http://YourServer/DeploymentWebservice/SCCM.asmx/GetAssignedSite
Parameters=SiteIP,SiteSubnet
SiteIP=ipAddress
SiteSubnet=ipSubnet

[DoAddToCollection]
WebService=
http://YourServer/DeploymentWebservice/SCCM.asmx/AddComputerToCollection
Parameters=MacAddress, UUID, CollectionID, ComputerName, AssignedSite
AssignedSite=siteCode

What does it do? It will first run a UserExit.vbs script. A UserExit script can be used to have custom code/rule processing within the standard gather step of MDT. (Please read Understanding BDD rule processing from Ben Hunter as one of the best sources about Rule Processing in general. It applies to BDD but almost everything is still valid in MDT.) The UserExit.vbs will call a couple of webservices and process the results to set some Environment variables. You probably wonder why we have an entry "AddToCollection" in Priority but no corresponding section. This is to show you a different way of dynamic Rule Processing. If we have a custom setting "CollectionID" configured with a value, the UserExit script will simply set the value of "AddToCollection" to "DoAddToCollection". So if it doesn't has a value it can't process anything as the section "AddToCollection" doesn't exist and if it has changed it will match the "DoAddToCollection" section and execute this webservice. Yes, this is not the best way to do it but I hope you are interested to see different ways to achieve the same result.

Here a snippet from the UserExit.vbs. Find the complete script attached:

Function UserExit(sType, sWhen, sDetail, bSkip)

    ' Get the necessary values for further processing
    oLogging.CreateEntry "Setting values for UserExit processing.", LogTypeInfo
    ' Get Computer ID
    oEnvironment.Item("MDTID") = GetComputerID

    ' Get collectionID
    oEnvironment.Item("CollectionID") = GetCustomSetting ("CollectionID")

    ' Check if computer has been prestaged
    sPrestaged = GetCustomSetting("Prestaged")
    If sPrestaged = "YES" Then
        oEnvironment.Item("Prestaged") = GetPrestagedStatus
    End If

    ' If CollectionID has been configured, add computer to collection
    If oEnvironment.Item("CollectionID") <> "" Then
        ' Get the SiteCode

        sAssignedSite = GetAssignedSite
        oEnvironment.Item("AssignedSite") = sAssignedSite
        ' Cameron specific. All MDT Collections are in CCC
        oEnvironment.Item("siteCode") = "CCC"

        If sAssignedSite = "" then
            oLogging.CreateEntry "Unable to determine assigned site using any available IP addresses", LogTypeWarning
        Else
            oLogging.CreateEntry "Client is assigned to site " & sAssignedSite, LogTypeInfo
            oLogging.CreateEntry "Will add Computer to Collection " & oEnvironment.Item("CollectionID"), LogTypeInfo
            oEnvironment.Item("AddToCollection") = "DoAddToCollection"
        End if
    End If

    UserExit = Success

End Function

Function GetComputerID
    Dim oService
    Dim oXML
    Dim iMDTID

    ' Set Default Value
    iMDTID = 0
    ' Create the web service instance

    Set oService = new WebService
    ' oService.IniFile = "SCCM_Bootstrap.ini"
    oService.SectionName = "GetMDTID"

    ' Make the web service call

    Set oXML = oService.Query
    If oXML is Nothing Then
        oLogging.CreateEntry "Unable to call GetMDTID web service.", LogTypeWarning
    Else
        iMDTID = oXML.SelectSingleNode("int").Text
        oLogging.CreateEntry "MDTID is " & iMDTID, LogTypeInfo
        'GetComputerID = iMDTID
    End If   
    GetComputerID = iMDTID
End Function

Function GetCustomSetting (Setting)
    Dim oService
    Dim oXML
    Dim sResult
   
    ' Set necessary setting for Webservice Call
    oEnvironment.Item("Setting") = sSetting

    ' Create the web service instance

    Set oService = new WebService

    ' oService.IniFile = "SCCM_Bootstrap.ini"
    oService.SectionName = "GetCustomSetting"

    ' Make the web service call

    Set oXML = oService.Query
    If oXML is Nothing then
        oLogging.CreateEntry "Unable to call GetCustomSetting web service.", LogTypeWarning
    Else
        sResult = UCase(oXML.SelectSingleNode("string").Text)
        oLogging.CreateEntry "value for " & Setting & " is " & sResult, LogTypeInfo
    End if   

    GetCustomSetting = sResult
End Function

 

If you are using this within the MediaHook and would like to use it with a SCCM_Bootstrap.ini just uncomment the ' oService.IniFile = "SCCM_Bootstrap.ini" lines.

Find attached the necessary sql scripts to create a sample CustomSettings table (with the CollectionID and Prestaged column as example) some corresponding views (which you need to update if you change the CustomSettings Table) and the Stored Procedures. And for sure all this will also be added to my past two posts Get access to the MDT Database and A Webservice for OSD and MDT Deployments. on the next update. (Don't want to publish new versions daily :-) )

 

And as always, use it at your own risk.

Download all files used in this post.

Comments

  • No Comments