Welcome to MSDN Blogs Sign in | Join | Help

Hotfix for HMC 4.0 and HMC 4.5 released to avoid that Mail gets sent to unintended mail recipients because legacyExchangeDN strings get re-used in the system

This is a short note that the HMC product group has released a critical hotfix for both HMC 4.0 and HMC 4.5. The issue is as follows

 

HMC 4.x uses the Exchange 2007 default mechanism to stamp the legacyExchangeDN. As a result, it uses just the alias to stamp it. Hence, there are possibilities where alias get re-used when one has been deleted.

 

When the legacyExchangeDN has been re-used, replying some of the old mail or sometimes, selecting the recipient through the Outlook nickname cache will result in the mail get delivered to the unintended recipients. This may result in information being sent or disclosed to unintended party.


This has been address by the fix outlined in the KB articles 976864 for HMC 4.5 and 976865 for HMC 4.0.

Please follow the normal support process for your Solution Support contract to obtain the fix for your environment.

Don't have a Solution Support Contract for your HMC environment? Check this link http://technet.microsoft.com/en-us/serviceproviders/cc299490.aspx

 

Posted by mkostersitz | 0 Comments

How to Call a Namespace procedure without using ProvTest.Exe

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 Powershell
Note 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# and
Calling the MPS Client from C# and VB.NET

Have fun coding

Till next time

Mike

Posted by mkostersitz | 0 Comments

MPS and concurrency

One question that comes up quite often is whether HMC Provisioning is "thread safe" i.e.. does it support multiple simultaneous provisioning actions. The answer to this question can be complicated, the simple answer is "yes, but there are caveats."

To understand the caveats better we have to understand the basic architecture of HMC Provisioning. For this discussion we will break the architecture into 3 blocks.    

HMC and MPF Namespaces

Layered business/service logic defined as XML workflow descriptions.

MPF Engine

COM service that executes requests based on workflows defined in the namespaces. This is the component that provides transaction based compensation/rollback support.

Providers and Underlying Product APIs

DLLs that run under the context of the MPF Engine, these DLLs wrap the Product specific APIs that are used to perform provisioning actions.

Now to understand the impact each of these components can have on the HMC Concurrency story we will start from the bottom and work our way up the stack.

Providers and Underlying Product APIs

The core provisioning capabilities of HMC are generally defined at, and limited by the underlying Product APIs, and specifically the way in which the Provider DLLs expose the product APIs. This is particularly true when it comes to the concurrency characteristics of HMC. The easiest way to explain this is to look at two core Providers and their concurrency characteristics.

  • SQL Provider: This provider supports execution of SQL Stored Procedures and ad-hoc requests within the context of a DTC transaction that can be bound to executing thread inside of the MPF Engine (more on MPF Engine Process Controller threads below). This allows for transaction scoping all the way down to the underlying System in this case SQL, leaving the responsibility for compensation in the case of a failure to DTC and SQL. This is a very powerful feature of the SQL Provider though one must consider that this also implies that any locks on a table or row in SQL are scoped to the entirety of the transaction. This must be taken into consideration when designing named procedures for Namespaces which orchestrate multiple SQL Provider requests. The SQL Provider is used mostly by the ManagedPlans Namespace for almost every single Plan related operation
  • Active Directory Provider: This provider uses standard directory services interfaces, so while the API exposed by this provider is fully thread safe there is no transactional scoping beyond the MPF Engine. Therefore, actions taken on one thread can directly impact other threads, ie. if thread A deletes an object before thread B tries to retrieve it, thread B will be impacted by the change made by thread A. This also must be taken into account when designing highly concurrent systems particularly when dealing with procedures that act on global, or organization wide objects.

These kinds of variations in concurrency characteristics exist across most of the MPF providers, though the SQL provider is unique in that it is the only provider that supports transactional scoping all the way down to the underlying system. It is generally these variations that result in currency related failures within in HMC.

MPF Engine

The MPF Engine was actually designed for high levels of concurrency. Each incoming request is processed on a separate "process controller" thread. Each process controller thread is fully isolated from other process controllers within the context of the MPF engine.  Each process controller thread is also an MPF transaction; all actions performed within the context of a transaction are persisted and if a failure occurs, these actions will be rolled back. So while this component in and of itself enables high concurrency request processing, as a developer you must take into account that other components in the system specifically the other two blocks in the architecture Providers and Underlying Product APIs (discussed above), and HMC and MPF namespaces (discussed below) have a significant impact on the concurrency behavior of the overall system.

HMC and MPF Namespaces

This is where the majority of the business or service logic is defined. Namespace logic is defined as multiple layers of named procedures that either call other named procedures or execute provider methods. The layering and orchestration capabilities of MPF are extensive and very powerful. Unfortunately, this is also the root of almost all concurrency related failures in HMC, some are easily avoided others require careful design consideration or in some cases external throttling and/or retry mechanisms. The following are some high level examples of concurrency related failures in HMC and MPF Namespaces.

MPF Requests that operate on global, or organization wide objects can cause failures under high concurrency

While this may seem fairly straight forward there are some corner scenarios where this can cause concurrency related problems.
Let's take for example the scenario where a SharePoint site is being created at the exact same time as a separate SharePoint site belonging to the same organization is being deleted. One might not expect these two requests to have any impact on each other however both rely on the organization wide SharePointSites service pointer for tracking purposes. If the request to delete a SharePoint site removes one of the site pointers at the same time that request to create a SharePoint site is enumerating the list of SharePoint sites the request to create a SharePoint site might fail because the Servicepointer is overwritten by the delete operation. This issue was alluded to above in the discussion about the Active Directory Provider, it is important to note though that any provider that interacts with Active Directory or other similar systems, Resource Manager has similar characteristics, is susceptible to this kind of failure.

MPF Requests that bundle multiple "locking" SQL Provider requests

This issue typically occurs when an MPF Named Procedure bundles two or more HMC Named Procedures, from the Hosted Namespace layer, that write to or read from the PlanManager Database. The root of this issue is that the Managed Plans Namesapce API utilizes the SQL Provider to manipulate the PlanManager Database. Since the SQL Provider establishes and holds locks for the duration of a transaction, transactions or requests that bundle multiple Managed Plans named procedures introduce an increased risk of SQL Deadlocks. SQL Deadlocks result in one or more of the MPF Requests failing.

Steps have been taken within the PlanManager database to try and prevent these deadlock scenarios under the most common scenarios where a customer might want to bundle requests for efficiency. However there are still some scenarios where bundling of requests will result in this failure. For example a transaction that attempts to add or modify a customer plan then subsequently assign the plan to a customer will fail under concurrency.
As a general rule one must take into account the cost of SQL transactions when designing highly orchestrated MPF named procedures, this goes along with considering the cost of rollback when bundling large numbers of procedure calls into a transaction.

OK now on to how do you design a custom namespace or process to facilitate successful bulk import or creation of organizations and users/mailboxes

As a general rule the HMC Provisioning System was designed to operate under high levels of concurrency. However, in a high scale, high volume HMC environment it may not be possible to avoid concurrency related issues completely. There are cases where a simple retry is the best solution to the problem. There are also cases however, where there are known failure scenarios and in these cases we strongly suggest that you take steps or put mechanisms in place to avoid concurrency, The most common of these cases are listed below

  • Bulk creation of Mailboxes within an organization.
    • It is best to avoid creation of a user, the mailbox and other mailbox features like UM in the same transaction. It is recommended to avoid these because of AD replication induced delays and PlanManager related concurrency failures.
  • Bulk creation and/or deletion of SharePoint sites within an organization.
    • Avoid deleting and creating the same site in the same transaction. Split the calls apart and put logic into the calling code to retry certain failed operations.
  • Bulk enablement of OCS users within an organization.
  • Avoid creating a user and immediately OCS enabling it. OCS Admin API does not have a preferredDomainController concept thus AD replication delay has to be taken into account.
  • Requests that bundle the creation/modification of a plan with assignment of a plan to an organization and or a user in the same organization

In general it is OK to bulk load multiple organizations in parallel however you should avoid the bulk provisioning of objects within a single organization in parallel. In other words requests to bulk load objects within a single organization boundary should be serialized.

Finally

While this covers some of the most common scenarios we see in support there are many others out there I am sure. Do you have a scenario not covered above which you are not sure if it is impacted by this discussion. Post a comment and I will be happy to expand the discussion 

Until next time (I promise it will not be 2 ½ years)

Mike

Posted by mkostersitz | 1 Comments

Finally an update

Well it has been a while, well a long while since I posted here.

It is a shame how simple things fall off the cliff between work and family.

I do promise though to be better from now on.

First a quick update on where I am at these days.

My family and I moved back to Austria last year and I am no longer a Program Manager for MPS.

Funny how things go I went full circle in Microsoft from Sales to Consulting to Development in Redmond and I ended up in Solution Support as a Principal Premier Field Engineer supporting what I designed over the last six years.

But enough about me and more about the Microsoft Provisioning System right away.

Posted by mkostersitz | 1 Comments

MPS SDK 2.0 release to the Web on 10/17/2006

OK OK I understand this is not the newest of news, and it seems it took us forever to get this out the door. But thanks to patient users, testers and last but not least our UA folks the MPS SDK 2.0 has finally been released to the web about a month and a half ago.

So far for the good news now for the details on what is in it and how to use it.

First there are three MSI Packages in the ZIP you get to download from this URL

http://www.microsoft.com/downloads/details.aspx?FamilyID=ce3fc537-86ae-4802-9a05-43e2a27a4b45&DisplayLang=en

There is also a README.htm file in the ZIP, which you definitely should read, it tells all about how to best prepare a MPS Development environment and how to install and configure the SDK Tools for Visual Studio 2005.

The two MSI files in the Documents Folder are the Visual Studio integrated documentation sets for Visual Studio 2003 and Visual Studio 2005 respectively. Install the one that applies to your Visual Studio version only.

The Microsoft Provisioning System SDK.MSI installs the Add In for the Visual Studio 2005 IDE, Sample code and Provider project templates for both Visual Studio Versions if present.

I strongly recommend using Visual Studio 2005 to take full advantage of all SDK features and functionalities as well as .NET 2.0 for your provider code.

One known issue we found recently is that for providers developed in with .NET 2.0 it is necessary to register the DLL in the GAC in addition to RegAsm.Exe /Codebase registration. This seems to be an effect of a .NET 2.0 fix deployed through Windows Update.

What's in store for the next version?

The next version will be released after the release of the Hosted Messaging and Collaboration 4.0 and Windows Based Hosting 4.5 Solutions. No fixed date has been set yet, once it has I will post it here.

Currently we are considering the following updates:

  • API documentation for the Terminal Services Provider and Namespace shipped in the Windows Based Hosting for Applications 1.0 Solution
  • API Documentation updates for changes introduced in Hosted Messaging and Collaboration 4.0 and Windows Based Hosting 4.5 Solutions
  • MPS Profiler/TraceView integration into the Visual Studio 2005 IDE

My next post will talk a about the changes to the development model and architecture in the Hosted Messaging and Collaboration 4.0 solution.

Stay tuned and keep the feedback coming

Mike

Posted by mkostersitz | 1 Comments

MPS SDK Beta 1 released for download

OK we finally got the SDK out the door and it will be available for download within the next 24 - 48 hours at the Microsoft Download Center at this Link

MPS SDK Beta 1 Direct Download Link

After you download the SDK unzip the Package to a location on the Harddrive. You will find two documents and an installer (msi) package.

You will have to have a MPS Development environment with Visual Studio 2005 set up and ready to go (check one of my other blog posts for how to get started on this)

The rest should be self explanitory.

Let me know what you think and provide loads of feedback :-)

Mike

Posted by mkostersitz | 2 Comments

MPS SDK Update

This is going to be a short one :-)

The MPS SDK for Visual Studio 2005 is going to be in Beta by the end of next week. If you want to get a early preview of the SDK tools and Docs please drop me a short note. You will need a completed NDA on File with Microsoft! Please work with your main Microsoft Contact if you need one to be set up. I will not be able to set up NDAs myself.

 

thanks

 

Mike

Posted by mkostersitz | 0 Comments

Developing a Provider for MPS Part 3: the SMTP Mail Sender Provider

Hello fellow coders. Here is part 3 of the how to develop a MPS Provider article.
Today I am going to focus on writing a provider which actually does something relatively useful.

The SMTPMailProvider (as I will call it from now on) will enable a MPS Named Procedure to send e-mail to a specified user.

The Project will consist of 3 parts.

  1. The Provider
  2. The Provider Namespace
  3. A Namespace which will create a user, mailbox enable that user and then send e-mail to the user. (this will require some sort of Mail system. For our purposes I will use the POP3 Mail service shipping in Windows Server 2003)

OK here we go

Setting up the environment

You will need to use add/remove Windows Component Wizard on one of the servers in your development environment and add the "E-mail Services" Component.

Part1: Writing the SMTPMailProvider

The SMTPMailProvider will use the System.Web.Mail Namespace to create and submit the Mail message it will have one public method called SendMail, the Method will take a couple of mandatory and a few optional parameters.

Mandatory Properties

  • sendTo
  • mailFrom
  • subject

Optional Properties

  • messageText
  • attachementPath
  • smtpServerName
  • messageFormat

How do we implement it:

Open Visual Studio 2003 and Create a new MPF Provider Project and Name it SMTPMailProvider

Add the System.Web.Mail Namespace to the references and insert

using System.Web.Mail;

Create the public sendMail Method by adding the Provider Method Atributes

[ProviderMethodAttribute("sendMail",
ProviderHandlerType.process,
Description="Sends an Email to one or more recipients",
AccessType=ProviderAccessType.publicAccess)]

 

Now create the method

public void sendMail(IXMLDOMNode node)
{
}

Now it is time to grab the mandatory properties from the incoming XML Request

// get the executeData node from the incoming XML request
IXMLDOMNode executeDataNode = node.selectSingleNode("/executeXml/executeData");

/// <remarks>
/// get the required elements from the incoming XML request
/// </remarks>
/// <param name="sendTo"> is required, delimit multiple receipients with semicolons(we are not checking for email address syntax</param>
/// <param name="mailFrom"> is the required (must be a valid email address the smtp server can relay)</param>
/// <param name="subject"> is required and gets inserted into the message subject</param>
string sendTo = this.GetRequiredElementValue(executeDataNode, "sendTo");
string mailFrom = this.GetRequiredElementValue(executeDataNode, "mailFrom");
string subject = this.GetRequiredElementValue(executeDataNode, "subject");

Now look if we have any optional parameters in the request

///<remarks>
///get the optional elements from the incoming XML request
///</remarks>
///<param name="messageText">string or HTML Blob that forms the message body</param>
///<param name="attachmentPath">the physical path to a fileattachment to be added to the message
/// there can only be one attachment in this implementation
/// if the path is invalid or not accessible the procedure will fail</param>
///<param name="smtpServerName">the NetBios, IP address or FQDN for the SMTP server
/// which will send the message, not supplying this paramater will default
/// to localhost</param>
///<param name="messageFormat">the format for the messagebody can be text or html</param>
string messageText = this.GetOptionalElementValue(executeDataNode, "messageText");
string attachmentPath = this.GetOptionalElementValue(executeDataNode, "attachmentPath");
string smtpServerName = this.GetOptionalElementValue(executeDataNode, "smtpServerName");
string messageFormat = this.GetOptionalElementValue(executeDataNode, "messageFormat").ToLower();

Ok that we relatively easy, we use th XML Handling methods which come with the provider Wizard template to retrieve the madatory and/or optional parameters.

For a relatively simple provider with only one method which does not require rollbach you can add the "action" code right here. For more complicated provider or providers with multiple methods and rollback requirements it is better to encapsulate each method into a seperate private class and then call it from here. For this sample I will add the action code right here

Let's new up a message object

//Create an empty Mail Message
MailMessage newMessage = new MailMessage();

Add the recipient, sender and subject to the message

newMessage.From = mailFrom;
newMessage.To = sendTo;
newMessage.Subject = subject;

Lets see if we have a message bod text, if you want to send an HTML Message then you will have to encode the HTML into the XML request, we will look into this a little later

if(messageText.Length != 0)
   {
      newMessage.Body = messageText;
   }
   

Now set the message format if the format string does not specify html or text then lets default to text and rather not fail.

if(messageFormat.Length != 0)
 {
         
switch(messageFormat)
         {
         // set the message format
         case "html":
            newMessage.BodyFormat=MailFormat.Html;
            break;
         case "text":
            newMessage.BodyFormat=MailFormat.Text;
            break;
         default:
            // we are not going to fail the send if an invalid 
            // messageFormat comes in just send as Text and we should be fine
            newMessage.BodyFormat=MailFormat.Text;
            break;
            }
}

Check if we have an attachment path and see if we can find it and attach it to the message

if(attachmentPath.Length != 0)
   // we got an attachmentpath lets try to attach the file
   // if this fails we will fail the request
   {
      try
         {
               MailAttachment newAttachment =
new MailAttachment(attachmentPath);
               newMessage.Attachments.Add(newAttachment);
         }
      catch(Exception e)
         {
               // Attachment adding failed
               
return ;
          }
      }

Here we will fail the request before sending the mail if we have encountered an error during attaching the file specified.

If we did not fail to add the attachment let's go and set the remainder of the optional paramters or the defaults.

// set the SMTP Server if any
if
(smtpServerName.Length != 0)
      {
            SmtpMail.SmtpServer =smtpServerName;
      }
            else
//default to localhost 
      {
            SmtpMail.SmtpServer ="localhost";
      }

In the code above we use the System.Web.Mail.SmtpMail Class to configure the mailserver we want to use to send the mail, this will default to localhost if none is specified.

Now lets send the message we have created above on its way

// now send the message
try
   {
      SmtpMail.Send(newMessage);
   }
      catch
(Exception e)
   {
      // sendig the message failed
      return
;
   }
}

Now that we are done with this lets create the Provider Namespace XML File, to do this edit the ProviderNS.XML from the solution explorer to look like this.

<namespace name="SMTPMailProvider" description="" readOnly="0" providerSource="SMTPMailProvider.Provider">

 <procedure name="sendMail" description="Sends an email using SMTP" access="public" type="write" perfEnabled="0" saveDataForRollback="0" auditEnabled="0"/>

</namespace>

Now we should be done with the base provider and the namespace so we can go ahead and build the solution hit CTRL-Shift-B, if all is well the build succeeded and we are good to go and register the DLL and go ahead and try the provider out.

Open a command prompt and CD to the Solution Folder in my case this is

C:\MPFSDK\Providers\SMTPMailProvider

Type the following commandline (without the line breaks of course)

\WINDOWS\Microsoft.NET\Framework\v1.1.4322\RegAsm.exe /codebase .\bin\Debug\SMTPMailProvider.dll

Ignore the warning for now. We are going to deal with the signing later on. Now we will go into the Provisioning Manager and register the provider Namespace. From the same commandline type

      provnamespace \MPFSDK\Providers\SMTPMailProvider\ProviderNS.xml

You should get a response like this

   The namespace(s) have successfully been added or updated.

The next step is going to be to create the ManagedMail Namespace which will allow us to send email and also setup a mail enabled user.

This will require some sort of mailenabled user we can send the mail to. I'll assume for now you have a mail system somewhere you can send mail to and also that there exists a SMTP Server we can use to send the mail from.

Developing a Provider for MPS Part 2

 OK Now that you have set up your environment (if you have not check out my previous post) let’s get some code done.

On the MPS Engine Server where you installed Visual Studio open the Visual Studio IDE.

Select File/New and you should see a new type of C# project there called "MPF .NET Provider".

Type in a name for the Provider and select a location where to put it. For this exercise I will call it HelloMPF and store it in C:\MPFSDK\Providers.

Note Visual Studio will create the Folders if they are missing. Your built DLL will end up in C:\MPFSDK\Providers\HelloMPF\bin\ debug or release depending on how you build it.

When you select the Class1.cs File in the Solution Explorer you a base provider built on the Base class so that it can do all the things you expect from a MPF Provider such as receiving XML <executeData> and returning the <response> XML.

So the only thing we now need to add is the code to grab any input data, work with the data and return it back as the response.

In the Code Window expand the Public Provider Methods and uncomment or type this block of sample code

[ProviderMethodAttribute("Say Hello",

ProviderHandlerType.process,

Description="Sample C# Provider Method",

AccessType=ProviderAccessType.publicAccess)]

public void MySampleMethod(IXMLDOMNode node)

{

// get the executeData node

IXMLDOMNode executeDataNode = node.selectSingleNode("/executeXml/executeData");

// get the required elements if any

string greeting = this.GetRequiredElementValue(executeDataNode, "greeting");

Now you have the input data from the request in your provider code. Let's create the output XML with the return values

The output will return the string "MPF says " and then insert the value we retrieved from the greeting input node.

Uncomment or type this block of code

// first we need to get the owning document for creating additional elements/nodes

IXMLDOMDocument parentXML = executeDataNode.ownerDocument;

// you can create a new node but be aware that the nodes may already exist due to optional input parameters

IXMLDOMElement newRootNode = (IXMLDOMElement)executeDataNode.selectSingleNode("helloWorld");

if (newRootNode == null)

{

newRootNode = parentXML.createElement("greeting");

executeDataNode.appendChild(newRootNode);

}

// add the <greeting/> node

this.AddOrUpdateNode(parentXML, newRootNode, "greeting", "MPF says " + greeting);

Ensure that you have your closing } at the end of the function.

There are some things in the code sample that comes in the Provider Wizard that need to be changed see highlighted text in the code blocks.

Now we are ready to build the provider Hit Ctrl+Shift+B or select Build Solution from the Menu Bar.

Now we have to create the XML Description of the provider which tells MPF what the provider can do. To do that click on the ProviderNS.XML File in the solution explorer and edit it so it looks like this

<?xml version="1.0" encoding="utf-8"?>
   <
namespace name="HelloMPF.ProviderNS" providerSource="HelloMPF.Class1"    xmlns="http://schemas.microsoft.com/MPF" xmlns:xsl=http://www.w3.org/1999/XSL/Transform 
description="Say Hello">

      <procedure name="Say Hello" type="read" access="public" description="Say Hello to the caller"/>

   </namespace>

Save the file.

We need to register the Provider DLL for COM, open a command prompt and CD into the C:\MPSSDK\Providers\HelloMPF Folder type the following command

C:\MPFSDK\Providers\HelloMPF>\WINDOWS\Microsoft.NET\Framework\v1.1.4322\RegAsm.e
xe /codebase .\bin\Debug\HelloMPF.dll

You can safely ignore the warning now. In the 3rd installment I will talk about how to sign and strongly type the provider so that it will not throw that warning.

Now open the Provisioning Manager from the Start Menu and right click on the Namespaces Node select import Namespace and specify the path

C:\MPFSDK\Providers\HelloMPF\ProviderNS.xml

And click OK. You should now see the HelloMPF.ProviderNS on the right hand side, when you select it the Say Hello Method should be visible in the left hand window.

Last but not least we will have to create a request to call the new provider, to do that go back to the IDE and select File/New/File ... under the General Category you will find "MPF Request" select that and hit Open

Edit the Template so it looks like this

<?xml version="1.0" encoding="utf-8" ?>

<!-- Documentation on the Request XML Schema can be found at "C:\Program Files\Microsoft Hosting\Provisioning\Development Tools\Help" -->

<request xmlns="http://schemas.microsoft.com/MPF" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <
data>
      
   <greeting>hello to you</greeting>
   </
data>
   <
procedure>
      <
execute namespace="HelloMPF.ProviderNS" procedure="Say Hello">
            <
before source="data" destination="executeData" mode="merge"/>
            <
after source="executeData" destination="data" mode="insert"/>
      </
execute>
   </
procedure>
</
request>

Back to our command prompt  we are now ready to submit the request. Type the following command

C:\MPFSDK\Providers\HelloMPF>provtest /x2 Request1.xml

You should get a response that looks somewhat like this

<response>
  <data xmlns="
http://schemas.microsoft.com/MPF">
    <greeting>hello to you</greeting>
    <executeData xmlns="">
      <greeting xmlns="
http://schemas.microsoft.com/MPF">hello to you</greeting>

      <greeting>
        <greeting>MPF says hello to you</greeting>
      </greeting>
    </executeData>
  </data>
</response>

If you get an error double-check the code and compare it to the code in the ZIP file that is attached to the post. If you are still stuck please post a reply here or better on the Forums in asp.net (see link in the links section)

I hope that this is valuable so far. In the third installment of this we will create a more useful provider, one that will let us send e-mail through MPS.

Until then happy coding

Mike

 

Posted by mkostersitz | 1 Comments

Developing a Provider for MPS

Hello Everyone,

I get asked every now and then how to create a custom provider to extend the functionality of MPS. Well here is the details on how  to go about it.

Before we start on this endevour let me go through a couple of prerequesites and common myths out there.

Myth 1: There is no SDK for MPS

somewhat BUSTED: Well while it is true that we do not have installable SDK that works with Visual Studio 2005 and .NET Framework 2.0 there is some help for devolpers available. When you start out searching for the SDK it might happen that you will  find the MPFSDK on some older distribution of MPF. Take my advice do not use it - if you have a desire to install VB6 and try it out be my guest though :-)

Later versions of MPF shipped a set of development tools which were designed to somewhat integrate with Visual Studio 2003 and provide some basic starter information for developers.

We are working on an update of the SDK tool set for Visual Studio 2005 and .NET 2.0 and that will be available later this year. If you are interested in getting added to the official preview list and get a peek at what we are doing there drop me a line with your e-mail address, company name and address so I can put you into our database of potential beta testers.

Myth 2: Microsoft does not support custom provider development for MPS

BUSTED: we encourage everyone to go ahead and expand on what MPS does so it fits their needs. Microsoft Customer Support Services will not support your own code but will provide you with all the support needed for running MPS in the Solution Environment.

So now that we have dealt with this on  to preparing your environment for MPS Development.

What you will need

  • Windows Server 2003 SP1 Machine
  • MPS Distribution from Windows Based Hosting 3.5 or Hosted Messaging and Collaboration 3.5
  • SQL Server 2000 SP4 install media
  • Visual Studio 2003 install media
  • A Domain Controller you have administrative access to (can be a Virtual Server)
  • A server running the service you are creating a provider for and which you can use to try out your provider (can be a Virtual Server)

Getting started

  • Install the OS on all machines (if not already done) + the latest Service Pack and Hotfixes
  • Join all machines to the domain
  • Install SQL Server 2000 and SQL Server 2000 SP4 on your development server
  • Install Visual Studio 2003 on your development server
  • Install MPS on your development server using the MPF.MSI following the Install Wizard and installing all components except the ISAPI Filter
  • Reboot the Development Server
  • If you need the other providers and Namespaces shipped with the solutions you can install the respective MSIs on the MPS Engine Server from the Solution Distribution.
    • Note: The MSIs will tell you that they can only be installed by the Deployment Tool. To get around this use this command line without the quotes "msiexec /i msiname.msi ENABLEUI=YES" (the parameter is case sensitive.

NOTE: Do NOT use this for a production system these instructions are for Development systems only!!!

  • Now that this is done let's set up the environment variables on the Development Server
    • Open the computer properties and on the Advanced Tab add the following path to the Path Variable C:\Program Files\Microsoft Provisioning\Tools
    • Add the Domain\MPFServiceAccts Group to the local Administrators Group
    • Restart the MPF Engine COM+ Application using the Component management MMC Snapin (dcomcnfg.exe).
  • open a Command Prompt and type provtest.exe /X3 "C:\Program Files\Microsoft Provisioning\Samples\Simple.xml"
    • You should get a response that is formated XML in green and blue looking like this

    <response>
       <data>
          <organizations>
             <organization name="tailspintoys.com"/>
          </organizations>
       </data>
    </response>

If the response is a error in yellow and red like this (Error Message might be different.

<response>
  <errorContext description="No provisioning engines are available to process the request." code="0xc2201908"/>

</response>

make sure that all the environment settings are done correctly. If in doubt please post questions on the Microsoft Provisioning Forum (Link is in the Links section of the Blog)

OK now you are almost ready to start developing. As kind of a warm up and to familiarize yourself with the MPS Architecture, how providers and named procedures work and how the named procedure XML schema works have a look at the MPFSDK.CHM file which has been installed in C:\Program Files\Microsoft Provisioning\Help on your development server.

Last but not least download and unzip the Visual Studio 2003 Preliminiary SDK Components to C:\MPSSDK, this will get you the neccesarry Interop DLLs and a couple of Samples how to get started. If your Visual Studio 2003 is not installed on the C:\ Drive make sure to adapt the install.cmd in the C:\MPSSDK\Installer Folder before you run it.The MPS SDK is available from downloads.microsft.com now.

Also note that these components are not production ready yet they are Alpha code so to speak. The interfaces though are fairly complete. If you develop a provider using them you should update to the release version of them once we ship them and there might be some changes between now and then but they will be small and in general the provider should work the same.

The next Post will deal with creating a simple provider and go into detail how to hook that provider into MPS and test it, so stay tuned, as well as have an update on where we are with the SDK Development effort and when to expect the Beta Release.

Until then

Mike

Posted by mkostersitz | 2 Comments

Why can MPS not run on a single Server?

Something I get asked a lot and actually this is a great and valid question so let me swing back in time a little and lets look where MPS Came from and what it was designed for.

1999: MPF is born and released as the provisioning solution for the First iteration of what is now the Solution for Hosted Messaging and Collaboration. Since this solution build on top of Exchange Server, Active Directory is a must. The target audience back then and to some extent today are larger hosters and the Phone Companies of this world, so reliablility and security and scalability were major design goals.

That said MPS can run in a minimal server configuration of 3 servers for MPF but you will not get reliability or scalability out of it because you have multiple points of failure which are not mitigated. Also keep in mind that the 3 servers only pertain to MPF and the Webservices not to the rest of the Servers required to host services like Exchange, SQL, Web and LCS Servers.

The Configuration would look something like this ...

Server1: Active Directory (recommended to have two of these)\
Server2: SQL Server 2000 SP4 and MPF Engine Server (recommended to split the roles for better performance and support for multiple Engine Servers)
Server3: MPS Frontend server (recommended to have at least 2 for loadbalancing)

Plus any servers for the services you plan to host.

NOTE: The above configuration is NOT recommended for production use but is suitable for Test and Development Environments.

That said we are working on a scaled down version of HMC for a future relase, as far as Windows Based Hosting goes you can scale it down pretty well since it is designed to be modular.

As always if you have any questions feel free to post them here.

Until next time

Mike

Posted by mkostersitz | 0 Comments

Dear Blog Long Time no See :-)

Back from a great vacation and all recharged here an update from snow less, rainless, sunny Redmond, WA.

The "Solution for Hosted Messaging and Collaboration 3.0" is out the door, and for the very first time in history (yeah I know sounds like a cliché) MPS now is supported on Windows Server 2003. So you, the customer, can do away with your (hopefully) last Windows 2000 Server in the Environment. The "Solution for Windows Based Hosting 3.0" will be updated shortly to reflect this change too.

The good news about the update to MPS 2.0 is that all namespaces and providers are supposed to work as before and no change is needed. Just make sure you read the Release Notes and the Updating from a previous version Documentation so you don't mess up your MPS Databases including the Plans database. Also you need two Hot fixes to make everything work as outlined in the documentation.

The new version has also an enhanced version of the Deployment Tool which allows installation of all MPS related components from a central location, so no need to run the tool from multiple servers any more.

In terms of control panel we are working with several vendors and they all are very enthusiastic about building a version of their control panel on top of our solution architecture utilizing our plumbing including MPS and focus more on the UI, CRM and other aspects to better compliment our solution. Make sure to check out http://www.microsoft.com/serviceproviders/hosting for news once there is an official announcement.

On a different note, thanks to all the replies and messages I received so far, keep that input coming. If you want to see a new feature or want to send feedback on MPS, feel free to post it here or send it to wbhcst@microsoft.com.

Look out for more exciting news soon ...

Mike

Posted by mkostersitz | 0 Comments

Welcome to my Blog

So how do we start this out? This is my first blog since back in the BBS times when I ran a FIDO Point in Austria ....(man am I that old already :-{)

Welcome is probably a good start ;-)

As a Program Manager at Microsoft I'm responsible for the Microsoft Provisioning System (MPS) used by Hosters to setup and configure customer accounts and services.

So this is mainly going to be about MPS and the tricks and treats (yeah it is that time of year again) useful and needed to make it a useful tool for the Community.

When I'm not having fun at work, which is basically only when I'm not there ;-) I spend my time with my family outside hiking, camping and having more fun :-)

So that is this for starters not much but something I will keep this updated from time to time so come back and ask what you have to ask.

Mike Kostersitz
Program Manager, Microsoft Corporation

P.S.:

to learn more about MPS or get other Hosting related questions answered check out

the Microsoft’s Technical Hosting Community on the ASP.NET Forums
http://www.asp.net/Forums/ShowForumGroup.aspx?tabindex=1&ForumGroupID=29

 

Posted by mkostersitz | 4 Comments
 
Page view tracker