Posted by: csaborio | December 5, 2007

Using ccpapi from the .Net 1.1 Framework

Last week during a customer engagement program at Microsoft, we had a company request something which I had never heard before. They wanted to use the ccpapi.dll from a 1.1 Framework application. The ccpapi is the API used to control Compute Cluster Edition. ccpapi runs on the 2.0 framework, and hence cannot be used directly with 1.1

Phil drew a diagram on an idea he thought about. He said it would be possible to build a wrapper around the ccpapi and expose one of the methods to be used from the 1.1 application. This sounded extremely familiar with the mechanism we used for wrapping a 32-bit DLL around a 64-bit COM exe.

Even though I do not have the diagram Phil drew, this pretty much narrows it down:

Since the wrapper is running on its own process space, it can be invoked by the 1.1 assembly with no problem whatsoever. In this case, I will give you the C++ code to the ISubmitJobWithTemplate function. This function receives a BSTRING object that points to the xml file that will be used for a particular job. Using this example, you can expose ANY method from the ccpapi (or any DLL for that matter).
Once you create your out of process (OOP) COM project, create a coClass that will work as the wrapper, in my case I called it CCPAPIWrapper. Import into your coClass header’s file the ccpapi tlb:
#import “ccpapi.tlb”
Create the method with the signature you would like, in this case, I just created a function with the following signature:
CCCPAPIWrapper::SubmitJobWithTemplate(BSTR xmlFile) {
}
And here is the code that will do the trick (most of this was Phil’s):

static const wchar_t *szServer = L”Kim38a”; //Server name

HRESULT hr = S_OK;

IClusterPtr ptrCluster;

hr = ptrCluster.CreateInstance(__uuidof(Cluster), NULL, CLSCTX_ALL);

if (FAILED(hr)) throw hr;

_bstr_t bstrServer(szServer);

hr = ptrCluster->Connect(bstrServer);

if (FAILED(hr)) _com_issue_errorex(hr, ptrCluster.GetInterfacePtr(), __uuidof(ptrCluster));

_bstr_t bstrHeadNode;

hr = ptrCluster->get_Name(bstrHeadNode.GetAddress());

if (FAILED(hr)) _com_issue_errorex(hr, ptrCluster.GetInterfacePtr(), __uuidof(ptrCluster));

//Create the Job

IJobPtr ptrJob;

ITaskPtr ptrTask;

long jobID;

_bstr_t bstrUser = L”b20\\user”; //Your username

_bstr_t bstrPwd = L”guest”; //Your password

//Create a job from template

hr = ptrCluster->CreateJobFromXmlFile(TemplatePath, &ptrJob);

if ((FAILED(hr)) || !(ptrJob)) _com_issue_errorex(hr, ptrCluster.GetInterfacePtr(), __uuidof(ptrCluster));

//Add the job to the scheduler

hr = ptrCluster->AddJob(ptrJob, &jobID);

if ((FAILED(hr)) || !(ptrJob)) _com_issue_errorex(hr, ptrCluster.GetInterfacePtr(), __uuidof(ptrCluster));

//Submit the job to the scheduler

hr = ptrCluster->SubmitJob(jobID, bstrUser, bstrPwd, true, 0);

if (FAILED(hr)) _com_issue_errorex(hr, ptrCluster.GetInterfacePtr(), __uuidof(ptrCluster));

return S_OK;

The final code can be found here in case you want to mess around with it (be warned, it has not been cleaned at all!)


Responses

  1. Hi!!! I´m trying to connect with a Cluster that have differents groups, and I need to get the information of the cluster objects like group name, ip address, network name, shares and the permission of the shares. Do you known how do this??? maybe in c#???

    Thanks

  2. Rogelio:

    Currently I do not have access to a cluster, but please bear with me for a week or so and I’ll will create the code that does exactly what you want. Just in case you’re curious, this can all be done with the CCP API using any .Net language such as C# and VB.Net.

    Regards,

    Christian

  3. Hi!!!! I contact with people in MS and they said me that CCP API doesn´t support it, that I need to use Cluster API, so I start with my application, with c++ and clusapi.h, and I have this:

    #include “stdafx.h” // inside #include “ClusDocEx.h” and inside this #include “ClusApi.h”

    void main()

    {

    HCLUSTER hCluster = NULL;

    HGROUP hGroup = NULL;

    HRESOURCE hResource = NULL;

    HCLUSENUM hEnum;

    HGROUPENUM hGroupEnum;

    HRESENUM hResourceEnum;

    DWORD chName;

    DWORD chNameGroup;

    DWORD chNameResource;

    DWORD dwType;

    DWORD dwIndex = 0;

    DWORD dwIndexGroup = 0;

    DWORD dwIndexResource = 0;

    DWORD cbNameSize = 0;

    WCHAR szName[512];

    WCHAR szNameGroup[9000];

    WCHAR szNameResource[9000];

    DWORD dwCluster = ERROR_SUCCESS;

    DWORD dwResult = ERROR_SUCCESS;

    DWORD dwResultGroup = ERROR_SUCCESS;

    DWORD dwResultResource = ERROR_SUCCESS;

    DWORD dwGetIp = ERROR_SUCCESS;

    hCluster = OpenCluster( L”CICNAS” );

    if(hCluster == NULL)

    {

    printf(”\nNo se encontro el Cluster”);Sleep(1000);

    }

    else

    {

    hEnum = ClusterOpenEnum(hCluster,CLUSTER_ENUM_GROUP);

    if(hEnum == NULL)

    {

    printf(”\nCluster fue Encontrado pero no se puede abrir”);Sleep(1000);

    }

    else

    {

    printf(”\nSe Encontro el Cluster!!!”);Sleep(1000);

    while( dwResult == ERROR_SUCCESS )

    {

    chName = sizeof (szName);

    dwResult = ClusterEnum(hEnum,dwIndex,&dwType, szName,&chName);

    if(dwResult == ERROR_SUCCESS)

    {

    printf(”\n\tNombre del Grupo= “);Sleep(1000);

    int i=0;

    while(szName[i])

    {

    printf(”%c”,szName[i]);

    i++;

    }

    hGroup = OpenClusterGroup(hCluster,szName);

    if(hGroup == NULL)

    {

    printf(”\n\tNo existen Grupos”);Sleep(1000);

    }

    else

    {

    ClusterGroupOpenEnum(hGroup,CLUSTER_GROUP_ENUM_NODES|CLUSTER_GROUP_ENUM_CONTAINS);

    hGroupEnum = ClusterGroupOpenEnum(hGroup,CLUSTER_GROUP_ENUM_CONTAINS);

    if(hGroupEnum == NULL)

    {

    printf(”\n\tError al recorrer Grupos”);Sleep(1000);

    }

    else

    {

    dwResultGroup = ERROR_SUCCESS;

    dwIndexGroup = 0;

    while( dwResultGroup == ERROR_SUCCESS )

    {

    chNameGroup = sizeof (szNameGroup);

    dwResultGroup = ClusterGroupEnum(hGroupEnum,dwIndexGroup,&dwType, szNameGroup,&chNameGroup);

    if(dwResultGroup == ERROR_SUCCESS)

    {

    printf(”\n\t\tszNameGroup s = “);Sleep(1000);

    int i=0;

    while(szNameGroup[i])

    {

    printf(”%c”,szNameGroup[i]);

    i++;

    }

    hResource = OpenClusterResource(hCluster,szNameGroup);

    if(hResource == NULL)

    {

    printf(”\n\t\tError!!!”);

    }

    else

    {

    ClusterResourceOpenEnum(hResource,CLUSTER_RESOURCE_ENUM_NODES|CLUSTER_RESOURCE_ENUM_DEPENDS);

    hResourceEnum = ClusterResourceOpenEnum(hResource,CLUSTER_RESOURCE_ENUM_NODES);

    if(hResourceEnum == NULL)

    {

    printf(”\n\t\tError!!!”);

    }

    else

    {

    dwResultResource = ERROR_SUCCESS;

    dwIndexResource = 0;

    while (dwResultResource == ERROR_SUCCESS)

    {

    chNameResource = sizeof(szNameResource);

    dwResultResource = ClusterResourceEnum(hResourceEnum,dwIndexResource,&dwType,szNameResource,&chNameResource);

    if(dwResultResource == ERROR_SUCCESS)

    {

    int i=0;

    while(szNameResource[i])

    {

    i++;

    }

    }

    dwIndexResource++;

    }

    }

    }

    }

    else if(dwResultGroup == ERROR_NO_MORE_ITEMS)

    {

    printf(”\n\tFin Grupo”);Sleep(3000);

    }

    else if( dwResultGroup == ERROR_MORE_DATA)

    {

    printf(”\n\tNo mas grupos”);Sleep(3000);

    }

    else

    {

    printf(”\n\tError!!!!”);Sleep(1000);

    }

    dwIndexGroup++;

    }

    }

    }

    }

    dwIndex++;

    }

    }

    dwResult = GetLastError();

    }

    SetLastError( dwResult );

    }

    I can get the Groups Names, the Files Shares names, the Network name of each group, the Physical disk of each group but I can´t get the Ip address, the path of the File Shares and the permission of each File Shares, If you can help me, well be nice. THANKS !!!!

    This is my email: rogelio.leyva@gmail.com


Leave a response

Your response:

Categories