Well, here is another one of my "How To" topics.
I get asked quite a bit: "How do we interact with MPS so we do not have to use Notepad and Provtest.exe."
So I would call this principle "Calling MPS programatically".
OK. So the good news first:The MPS Client is a good old fashioned COM Object with a couple of interfaces we can use from almost any programming language. If you keep a basic rule in mind things should turn out pretty well J
Rule #1: Do Not Break MPS Loadbalancing. Load balancing in MPS is handled by the MPS Client. When you submit a request to the client, the client will connect to the MPFConfig Database and ask for a list of available MPS Engine servers and then start submitting the requests to each engine in the list in a round robin fashion. So imagine your code does something like this Disclaimer: Pseudo code ahead! For illustration purposes only.
For i=1 to 10 myResult= submitMPSRequest strXML(i),strNamespace,strProcedure next
function submit MPSRequest(string XMLRequest, strNSName, strProcName) myMPSClient = CreateObject("MPSClientCOMObject") return myMPSClient.SubmitTrustedRequest(strXML,strNSName,strProcName) end function
So what will happen when we run this?
Correct: Every time a request is submitted a new MPSClient Object is created and that instance will always submit the request to the first engine in the list of results. So no load balancing will occur.So the correct way to structure this would be
Disclaimer: Pseudo code ahead! For illustration purposes only.
Global myMPSClient = CreateObject("MPSClientCOMObject") For i=1 to 10 myResult= submitMPSRequest strXML(i),strNamespace,strProcedure next
function submit MPSRequest(string XMLRequest, strNSName, strProcName) return myMPSClient.SubmitTrustedRequest(strXML,strNSName,strProcName) end function
So what will happen when we run this code?
Every time a request is submitted the same MPSClient Object is used and since it is only instantiated once it will do the correct load balancing between all available engines.
OK now off to real code
Let's say we want to create a bunch of organizations in HMC for the sake of this sample. The first thing we need is a template XML file we can use to fill in our properties before we submit it to MPS.
Sample CreateOrganization.xml file ( I used one from the samples folder on the MPS Engine and cleaned it up a bit )
<?xml version="1.0" encoding="utf-8" ?> <request> <data> <name/> <policyName/> <container/> <description/> <preferredDomainController/> </data> <procedure> <execute namespace="Managed Active Directory" procedure="CreateOrganization"> <before source="data" destination="executeData" mode="merge"/> <after source="executeData" sourcePath="org" destination="data" mode="insert"/> </execute> </procedure> </request>
Since VBScript is so old school I will keep this one short and not spend much time with it.
--------------- Script starts here --------
'INSTANTIATE THE MPF CLIENT OBJECT Set objMPFClient = CreateObject("Provisioning.ProvEngineClient") For i=1 to 10 Wscript.echo "Created OU: " & CreateOrganization("MyTestOrg" & i, "Customer", "Test Org", "OU=ConsolidatedMessenger,OU=Hosting,DC=Fabrikam,DC=Com") next
Function CreateOrganization(xi_OrgName, xi_PolicyType,xi_Description, xi_strContPath)
'LOAD THE XML OBJECT
Set objXML = CreateObject("MSXML2.DOMDocument") 'LOAD XML TEMPLATE strXmlFile = "CreateOrganization.xml" objXml.Load (strXmlFile) 'SET THE ORG NAME Set objOrg = objXml.selectSingleNode("/request/data/name") objOrg.Text = CStr(xi_OrgName)
'SET THE POLICY TYPE Set objOrg = objXml.selectSingleNode("//*/data/policyName") objOrg.Text = CStr(xi_PolicyType)
'SET THE CONTAINER Set objOrg = objXml.selectSingleNode("//*/data/container") objOrg.Text = xi_strContPath
'SET THE DESCRIPTION Set objOrg = objXml.selectSingleNode("//*/data/description") objOrg.Text = CStr(xi_Description)
'SET THE PREFERRED DOMAIN CONTROLLER Set objOrg = objXml.selectSingleNode("//*/data/preferredDomainController") objOrg.Text = CStr(prefDC)
'SUBMIT THE REQUEST strXMLResponse = objMPFClient.SubmitRequest(objXML.xml, "Managed Active Directory", _ "CreateOrganization")
'GET LDAP PATH FROM RESPONSE objXml.LoadXML(strXMLResponse) Set objOrg = objXml.selectSingleNode("//*/data/org")
CreateOrganization = objOrg.getAttribute("path")
End Function
Now to something more up to date – Windows PowershellNote that we need to use a MSXML2.DOMDocument instead of a System.XML Object this is because MPS does not "understand" System.XML Objects.,
$mpsclient=New-Object -ComObject "Provisioning.ProvEngineClient" function CreateOrganization([string]$strOrgName,[string]$strPolicyName,[string]$strDescription,[string]$strPath,[string]$strDC) { $xmlRequest = New-Object -ComObject "MSXML2.DOMDocument" $xmlRequest.load("CreateOrganization.xml") $xmlRequest.SelectSingleNode("//*/data/name").Text=$strOrgName $xmlRequest.SelectSingleNode("//*/data/policyName").Text=$strPolicyName $xmlRequest.SelectSingleNode("//*/data/container").Text=$strPath $xmlRequest.SelectSingleNode("//*/data/description").Text=$strDescription $xmlRequest.SelectSingleNode("//*/data/preferredDomainController").Text=$strDC
return $mpsclient.SubmitRequest($xmlRequest.xml,"Managed Active Directory","CreateOrganization") }
for($i=1;$i -le 10;$i++) { CreateOrganization "MyTestOrg_$i" "customer" "Test Org" "LDAP://OU=ConsolidatedMessenger,OU=Hosting,DC=Fabrikam,DC=Com" "AD01" }
Soon to follow something even more interesting – Calling the MPS WebServices (HMC 4.5) from C# andCalling the MPS Client from C# and VB.NET
Have fun coding
Till next time
Mike