Connecting to the Cluster
To access the cluster, call the ICluster::Connect method and pass the computer name of the cluster's head node. If you are logged on to the head node, you can use "localhost" as the name; otherwise, you must specify the name of the head node. The name can be the head node's computer name or its fully qualified domain name.
The following C++ example shows how to connect to a cluster. The example assumes that pCluster
points to a valid ICluster instance.
if (ConnectToServer(pCluster, L"localhost"))
{
// Do something
}
// Connect to the specified cluster. Set pClusterName to the name of
// the cluster's head node.
BOOL ConnectToServer(ICluster* pCluster, LPWSTR pClusterName)
{
HRESULT hr = S_OK;
// Connect to the server.
hr = pCluster->Connect(_bstr_t(pClusterName));
if (FAILED(hr))
{
wprintf(L"Failed to connect to cluster, %s.\n", pClusterName);
return FALSE;
}
wprintf(L"Connected to cluster, %s.\n", pClusterName);
return TRUE;
}
The following C# example shows how to connect to a cluster. The example assumes that cluster
points to a valid ICluster instance and that the value of nodeName
is the name of the head node or "localhost".
try
{
cluster.Connect(nodeName);
}
catch
{
string message = "Failed to connect to the cluster, " + nodeName + ".\n\n";
message = message + cluster.ErrorMessage + ".";
MessageBox.Show(message, "Connection failure");
}
If you do not know the names of the head nodes in a domain, you can use Active Directory to search for the names, as shown in the following example.
// Link to Activeds.lib and Adsiid.lib
#include <vector>
#include <activeds.h>
std::vector<LPWSTR> pHeadNodes;
DWORD size = 0;
FindConnectionPoints(pHeadNodes);
if (!pHeadNodes.empty())
{
size = (DWORD) pHeadNodes.size();
wprintf(L"Found the following %d head nodes.\n", size);
for (DWORD i=0; i<size; i++)
{
wprintf(L"%s\n", pHeadNodes[i]);
}
ClearConnectionPoints(pHeadNodes);
}
// Use Active Directory to find the head nodes of the compute clusters
// in a domain.
void FindConnectionPoints(std::vector<LPWSTR>& pHeadNodes)
{
HRESULT hr = S_OK;
IADs* pObject = NULL;
IDirectorySearch* pSearch = NULL;
ADS_SEARCH_HANDLE hSearch;
WCHAR szPath[MAX_PATH];
VARIANT var;
LPWSTR pNodeName = NULL;
BOOL fAllocationError = FALSE;
size_t length = 0;
// Bind to LDAP://rootDSE.
hr = ADsOpenObject(L"LDAP://rootDSE",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IADs,
(void**)&pObject);
if (FAILED(hr))
{
wprintf(L"Cannot execute query. Cannot bind to LDAP://rootDSE.\n");
return;
}
hr = pObject->Get(_bstr_t("defaultNamingContext"), &var);
if (SUCCEEDED(hr))
{
// Build path to the domain container.
StringCchPrintf(szPath, MAX_PATH, L"LDAP://");
StringCchCatN(szPath, MAX_PATH, var.bstrVal, MAX_PATH - wcslen(szPath));
VariantClear(&var);
// Get the DirectorySearch object used to search Active Directory.
hr = ADsOpenObject(szPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IDirectorySearch,
(void**)&pSearch);
if (FAILED(hr))
{
wprintf(L"Failed to create DirectorySearch object, 0x%x.\n", hr);
}
else
{
// This attribute contains the FQDN of the head node.
LPWSTR pszAttrs[] = { L"servicednsname" };
DWORD dwCount = sizeof(pszAttrs)/sizeof(LPWSTR);
ADS_SEARCH_COLUMN DnsNameColumn;
// Search for the service connection points.
hr = pSearch->ExecuteSearch(L"(&(objectClass=ServiceConnectionPoint)(serviceClassName=MicrosoftComputeCluster))",
pszAttrs,
dwCount,
&hSearch);
if (FAILED(hr))
{
wprintf(L"pSearch->ExecuteSearch failed, 0x%x\n", hr);
}
else
{
hr = pSearch->GetFirstRow(hSearch);
if (SUCCEEDED(hr))
{
while( hr != S_ADS_NOMORE_ROWS && !fAllocationError)
{
hr = pSearch->GetColumn(hSearch, L"servicednsname", &DnsNameColumn );
if ( SUCCEEDED(hr) )
{
length = wcslen(DnsNameColumn.pADsValues->CaseIgnoreString) + 1;
pNodeName = (LPWSTR) malloc(length * sizeof(WCHAR));
if (pNodeName)
{
StringCchCopy(pNodeName, length+1, DnsNameColumn.pADsValues->CaseIgnoreString);
pHeadNodes.push_back( pNodeName );
}
else
{
wprintf(L"Failed to allocate memory for node name.\n");
pSearch->FreeColumn( &DnsNameColumn );
fAllocationError = TRUE;
ClearConnectionPoints(pHeadNodes);
continue;
}
pSearch->FreeColumn( &DnsNameColumn );
}
// Get the next row.
hr = pSearch->GetNextRow( hSearch);
}
}
pSearch->CloseSearchHandle(hSearch);
}
pSearch->Release();
}
}
pObject->Release();
}
// Free the node names in the vector and clear the vector.
void ClearConnectionPoints(std::vector<LPWSTR>& pHeadNodes)
{
DWORD size = 0;
if (!pHeadNodes.empty())
{
size = (DWORD) pHeadNodes.size();
for (DWORD i=0; i<size; i++)
{
if (pHeadNodes[i])
free(pHeadNodes[i]);
}
pHeadNodes.clear();
}
}
// Reference System.DirectoryServices;
private void LoadHeadNodes()
{
string dnsName;
// Bind to current domain
searchRoot = new DirectoryEntry("LDAP://rootDSE");
domain = new DirectoryEntry("LDAP://" + searchRoot.Properties["defaultNamingContext"][0]);
searchRoot.Dispose();
string domainName = domain.Name.Substring(3); // DC=name
lblSelectDomain.Text = "Select the cluster to connect to from the " + domainName + " domain.";
// Search for head nodes in current domain
string[] propsToLoad = new string[] { "servicednsname" };
string filterForAllHeadNodes = "(&(objectClass=ServiceConnectionPoint)(serviceClassName=MicrosoftComputeCluster))";
searcher = new DirectorySearcher(domain, filterForAllHeadNodes, propsToLoad);
SearchResultCollection results = searcher.FindAll();
cbHeadNodes.BeginUpdate();
// Enumerate head nodes and load list
foreach (SearchResult result in results)
{
int index = 0;
dnsName = (string)result.Properties["servicednsname"][0];
// Get the name from the fully qualified path, if qualified.
if ((index = dnsName.IndexOf('.')) > 0)
cbHeadNodes.Items.Add(dnsName.Substring(0, index));
else
cbHeadNodes.Items.Add(dnsName);
}
results.Dispose();
// Get name of local computer
string localHost = System.Net.Dns.GetHostEntry("LocalHost").HostName;
string filterForLocalHeadNode = "(&(objectClass=ServiceConnectionPoint)(serviceClassName=MicrosoftComputeCluster)(servicednsname=" + localHost + "))";
// Change filter string filter on servicednsname too
searcher.Filter = filterForLocalHeadNode;
results = searcher.FindAll();
// If the local computer is a head node, make its entry the selected item.
if (results.Count > 0)
{
dnsName = (string)results[0].Properties["servicednsname"][0];
cbHeadNodes.SelectedItem = dnsName.Substring(0, dnsName.IndexOf('.'));
}
else
{
cbHeadNodes.SelectedIndex = 0;
}
cbHeadNodes.EndUpdate();
results.Dispose();
domain.Dispose();
}