Dos, tres... muchos clústeres de cálculo: búsqueda de clústeres en Active Directory

Por Los chicos del scripting de Microsoft

Nuestro idioma es maravilloso. Nos permite decir cosas como hay más días que ollas, aunque no a un chico del scripting: quizá no sepa qué es una olla). Bien, también podemos afirmar que hay más configuraciones de clústeres de cálculo que días. Y es que, realmente, hay tantas configuraciones de clústeres de cálculo como peces en la mar (pero mejor que no se enteren los chicos del scripting aficionados a la pesca: podrían esquilmar los caladeros en cuestión de días). También se podría pensar que un excesivo número de administradores del sistema podría estropear un clúster de cálculo, pero en realidad ocurre más bien lo contrario: cuantos más administradores del sistema haya, mejor. No culpe a los chicos del scripting: nosotros no inventamos este enrevesado idioma; simplemente lo utilizamos mal.

Independientemente del dicho que se emplee con ellos, los clústeres de cálculo adquieren diferentes formas y tamaños. Algunas organizaciones pueden ampliar un clúster hasta el equivalente de un enorme súper-equipo con cientos de nodos, utilizado por cada persona de la organización para realizar tareas de cálculo de gran calibre. Otras, en cambio, pueden distribuir pequeños equipos en paquetes más reducidos entre diversos departamentos. En este último supuesto, es probable que se implementen numerosos clústeres de cálculo más pequeños en el mismo segmento de red y el mismo dominio de Active Directory. Si en todo esto ve reflejada su vida como administrador de clústeres de cálculo, esperamos que este artículo y la secuencia de comandos le sirvan de bálsamo, de niña de sus ojos, de objeto de deseo, de (ponga aquí el tópico que más le guste).

Dr. Scripto: Un pollo en cada cazuela y un clúster de cálculo en cada escritorio.

En esta página

Información sobre ADO
Información sobre Cscript
¿Qué hay en una secuencia de comandos?
Estampida de clústeres
Recursos

Información sobre ADO

Al instalar Compute Cluster Server (CCS) en Windows Server 2003, se aporta al sistema una gran infraestructura que va más allá del sistema operativo. Entre otras cosas, CCS se integra con Active Directory para la administración de identidades y dominios.

Con objeto de controlar la mayoría de los aspectos relacionados con la autorización de usuarios y grupos, así como la autenticación en los clústeres de cálculo de las secuencias de comandos y aplicaciones que utilice, puede hacer uso de las interfaces de servicio de Active Directory (ADSI, Active Directory Service Interfaces), la principal biblioteca de secuencias de comandos de Windows para Active Directory.

No obstante, tal vez no sepa que existe otra biblioteca de secuencias de comandos que también puede ayudarle a automatizar la administración de su directorio. Los objetos de datos ActiveX (ADO) constituyen, principal y primordialmente, una tecnología de programación y creación de secuencias de comandos para bases de datos. Ofrecen una coherente interfaz de programación a través de una amplia gama de orígenes de datos: desde archivos de texto a hojas de cálculo, pasando por diversos tipos de bases de datos. Dado que un directorio es también un tipo de base de datos, ADO se puede utilizar como una flexible herramienta para creadores de secuencias de comandos y programadores que trabajen con Active Directory. Aquí, ADO ofrece una ventaja particular respecto a ADSI: se trata, a menudo, del método más apropiado para realizar búsquedas de recursos en un contenedor de directorios de varios niveles.

En el caso que nos atañe, nuestro objetivo es la búsqueda de un determinado tipo de recurso: clústeres de cálculo. Si tiene que administrar varios clústeres en el tipo de entorno al que aquí nos referimos, ADO puede resultar de gran utilidad para las secuencias de comandos de administración de usuarios, grupos y equipos en estos clústeres distribuidos.

Información sobre Cscript

Antes de echar un vistazo al código de la secuencia de comandos, comprobemos si nuestro entorno de secuencias de comandos está preparado. Para la mayoría de las secuencias de comandos, deberá disponer de privilegios administrativos en los equipos en los que éstas se ejecutarán.

En tal caso, no obstante, cualquier persona con credenciales de usuario del dominio podría ver los clústeres de cálculo que haya en el dominio, y cualquiera que disponga de permisos como usuario del clúster podría obtener información del estado del clúster y sus nodos. Como ocurre con cualquier secuencia de comandos de Windows, sin embargo, las credenciales bajo las cuales se ejecuta nuestra secuencia de comandos no permiten que ésta lleve a cabo ninguna acción no permitida por dichas credenciales en la interfaz gráfica del usuario ni a través de otras herramientas de línea de comandos.

Si no se ejecutaron secuencias de comandos administrativas desde la estación de trabajo o el nodo de cabeza donde se ejecute esta secuencia de comandos, asegúrese de que el host de secuencias de comandos predeterminado de Windows Script Host sea Cscript.exe, el host de línea de comandos, y no Wscript.exe, el host de la interfaz gráfica del usuario (a menos que le encante hacer clic en Aceptar una y otra vez).

Para que Cscript.exe sea la opción predeterminada, escriba lo siguiente en el símbolo del sistema:

cscript //h:cscript //nologo //s

El conmutador //h configura el host de secuencias de comandos predeterminado, el conmutador //nologo evita que un par de líneas de verborrea irrelevante se ejecute cada vez que inicie la secuencia de comandos y el conmutador //s guarda esta configuración como predeterminada.

¿Qué hay en una secuencia de comandos?

Pasemos entonces al quid de la cuestión, al meollo del asunto o adonde quiera que deseemos llegar. Esta secuencia de comandos localiza todos los clústeres de cálculo de un contenedor de Active Directory y comprueba las capacidades y el estado de cada clúster y sus nodos. Utiliza dos tecnologías de secuencias de comandos principales: ADO, para localizar los clústeres de cálculo del contenedor de Active Directory que especifique; y la API de secuencia de comandos de Compute Cluster Pack (CCP), para devolver la información sobre clústeres y nodos. Esta secuencia de comandos también tiene la ventaja de algunas capacidades integradas de VBScript para el análisis de cadenas y el control de errores.

Como ocurre en la mayoría de las secuencias de comandos más extensas incluidas en Secuencias de comandos para Compute Cluster Server (que puede estar en inglés), ésta comienza con una sección en la que se definen las constantes y variables. Antes de ejecutar la secuencia de comandos, se debe cambiar el valor asignado a strContainer por un contenedor real de su estructura de Active Directory.

Const ADS_SCOPE_SUBTREE = 2
strContainer = "CN=computers,DC=fabrikam,DC=com" 'Accessible AD container.
strObjectCategory = "ServiceConnectionPoint" 'For CCS
strServiceClassName = "MicrosoftComputeCluster"

Las siguientes 20 líneas, más o menos, configuran la infraestructura de ADO para realizar la búsqueda del contenedor de ADO. La mayor parte de esta sección sirve como modelo y se puede utilizar con la mayoría de las consultas de ADO en Active Directory. Comience creando dos referencias a objetos: una referencia a un objeto de conexión que indique a ADO con qué tipo de proveedor de datos desea conectarse; y otra a un objeto de comando que defina la consulta que desee realizar, el contenedor donde llevarla a cabo y el tipo de conjunto de datos que debe devolver.

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")

Una vez asignado el proveedor y abierto el objeto de conexión, este último se asigna a la propiedad ActiveConnection del comando:

objConnection.Provider = ("ADsDSOObject")
objConnection.Open "Active Directory Provider"
objCommand.ActiveConnection = objConnection

A continuación comienza el trabajo sobre el objeto de comando. La configuración del tamaño de la página es necesaria si se desea recuperar toda la información que se busque. (Para obtener más información sobre tamaños de página, consulte este Enigma de las secuencias de comandos, que puede estar en inglés). La constante ADS_SCOPE_SUBTREE, que representa el número entero 2, se asigna a la propiedad Searchscope para indicar a ADO que busque de forma recursiva en el contenedor especificado y todos sus sub-contenedores. Y el atributo "cn" (de "common name", nombre común) se asigna la propiedad Sort On para indicar a ADO que ordene los datos por el nombre de los clústeres de cálculo.

objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
objCommand.Properties("Sort On") = "cn"

El código más complejo de esta sección define la consulta y la asigna a la propiedad CommandText del objeto de comando. ADO permite utilizar sintaxis SQL o LDAP para realizar consultas en el directorio. En este caso utilizamos SQL:

objCommand.CommandText = _ 
 "SELECT serviceClassName,servicednsname FROM 'LDAP://" & _
 strContainer & "' " & _
 "WHERE objectCategory = '" & strObjectCategory & "' " & _
 "AND serviceClassName = '" & strServiceClassName & "'"

La consulta recupera dos atributos del contenedor: serviceClassName y servicednsname (filtrados por la cláusula WHERE). Esta cláusula indica que la consulta sólo precisa objetos que cumplan dos criterios: su categoría debe ser ServiceConnectionPoint y su serviceClassName debe ser MicrosoftComputeCluster. Cualquier objeto que cumpla estos requisitos debe ser un clúster de cálculo, según el esquema de Active Directory.

Una vez cargado el objeto de comando para los clústeres de cálculo, la secuencia de comandos se inicia utilizando el método Execute. Este método lleva a cabo la consulta en el contenedor. A continuación, Execute ubica la captura en un objeto que representa al conjunto de registros que cumplen los requisitos de la consulta. Asignamos una referencia a este objeto a una variable denominada objRecordSet. ¿Quién dijo que la nomenclatura de las variables no es un arte?

Set objRecordSet = objCommand.Execute

En este momento de clímax, con nuestro conjunto de registros recién empaquetado, se produce un scriptus interruptus para comprobar la existencia de errores utilizando el objeto Err integrado en VBScript (que funciona en equipo con la instrucción On Error Resume Next, al comienzo de la secuencia de comandos). ¿Que ocurre si el comando Execute no funciona? Normalmente, esto significa que el contenedor no está disponible, por lo que la secuencia de comandos utiliza la función HandleError, le pasa un mensaje adecuado y le permite mostrar la información del error de VBScript. Acto seguido, toma su consulta y se marcha, puesto que no hay conjuntos de registros con los que continuar.

On Error Resume Next
...
If Err Then
  HandleError "ERROR: Unable to find container: " & strContainer
  WScript.Quit
End If

Si el comando no devuelve ningún error, la secuencia de comandos mostrará un mensaje para indicar que se está realizando la búsqueda en el contenedor y proseguirá con el conjunto de registros. Ahora, si quisiéramos conocer los nombres de los clústeres de cálculo que están ahí fuera, simplemente tendríamos que recorrer el conjunto de registros hasta llegar a ellos. Pero en esta secuencia de comandos, ya que nos hemos tomado la molestia de localizarlos, también vamos a recopilar información sobre cada clúster y sus nodos. Para hacerlo, debemos usar la secuencia de comandos API de Compute Cluster Pack.

Entonces, antes de empezar a recorrer el conjunto de registros, aprovechemos la ocasión para crear una referencia al objeto base de la API de CCP, utilizando el identificador mediante programación "Microsoft.ComputeCluster.Cluster", que debe ser un nombre conocido por todos los entusiastas de las secuencias de comandos de Compute Cluster Server. De nuevo comprobaremos si existen errores, pero esta vez no saldremos si los hay. Simplemente enviaremos un mensaje a HandleError indicando que no podemos extraer información sobre clústeres y nodos de cada clúster de cálculo detectado. La secuencia de comandos, no obstante, puede proseguir y, al menos, enumerar los nombres de los clústeres que se obtengan con ADO.

Set objComputeCluster = CreateObject("Microsoft.ComputeCluster.Cluster") 
If Err Then
  HandleError "ERROR: Unable to find Compute Cluster Pack API " & _
   "on this computer. Cluster and node settings not available."
End If

Sí, lo sabemos: ya va siendo hora de empezar a recorrer el conjunto de registros y encontrar esos clústeres de cálculo; pero aún queda otro paso preliminar. No queremos perder el tiempo recorriendo conjuntos de registros que no contengan registros, lo que significaría que no se encontraron clústeres de cálculo. Así que nos aseguraremos de que la propiedad EOF (End Of File, fin de archivo) del objeto conjunto de registros no sea True, pues es una doble negación para indicar que, al menos, existe un registro.

If Not objRecordSet.EOF Then

Bien, ahora podemos empezar a divertirnos. Primero utilizaremos el método MoveFirst para asegurarnos de que nos encontramos al comienzo del conjunto de registros. Después, iniciaremos un bucle Do Until, que indica al motor de VBScript que debe llevar a cabo las acciones especificadas entre "Do Until" y "Loop" hasta completarlas todas en cada registro del conjunto. Cada bucle comienza comprobando si se ha alcanzado el final del archivo, en cuyo caso la secuencia de comandos abandona el bucle y continúa ejecutándose. Si no nos encontramos al final del archivo, continuaremos en el bucle. Cada vez que la secuencia de comandos llega al final del bucle, utiliza el método MoveNext para pasar al siguiente registro del conjunto y, a continuación, vuelve a comprobar si se llega al final de éste antes de realizar nuevamente el bucle.

  objRecordSet.MoveFirst 
  Do Until objRecordSet.EOF
    ...
    objRecordSet.MoveNext
  Loop

En este bucle, a su vez, con cada registro volcamos el valor del campo "servicednsname" en una variable y mostramos el nombre completo de DNS. Tendrá un aspecto similar a "srv-ccs-1.computers.fabrikam.com".

    strClusterDnsName = objRecordSet.Fields("servicednsname").Value
    Wscript.Echo vbCrLf & "Cluster DNS Name: " & strClusterDnsName

Acto seguido, extraemos nuestras funciones de análisis de cadenas de VBScript, Left e InStr, y comenzamos la división. InStr se utiliza para hallar el primer punto en la cadena, mientras que Left se utiliza para podar la parte de la cadena ubicada a la izquierda del punto. Así obtenemos el nombre del host, que debe ser también el nombre del clúster de cálculo.

    strClusterName = Left(strClusterDnsName, _
     (InStr(strClusterDnsName, ".") - 1))

Lo sabemos: no es tan elegante como una expresión regular. Pero funciona. Y si realmente prefiere usar una expresión regular en su lugar, VBScript tiene un objeto RegExp para el análisis a su entera disposición.

Ahora tenemos nuestro conjunto de registros de clústeres de cálculo incluidos en este contenedor, el nombre de cada clúster y la referencia a nuestro objeto Cluster. Así, en cada bucle utilizaremos el método Cluster.Connect para conectarnos al clúster y obtener sus propiedades, de nuevo comprobando la existencia de errores en caso de que el clúster no sea accesible.

    objComputeCluster.Connect(strClusterName)
    If Err Then
      HandleError "ERROR: Unable to connect to this compute cluster."
    Else

Tras obtener y repetir las propiedades del clúster, utilizamos el método Cluster.ComputeNodes para obtener una recopilación de los nodos de este clúster.

      Set colNodes = objComputeCluster.ComputeNodes

Recorremos la recopilación de nodos, esta vez utilizando un bucle For Each, que es para las recopilaciones lo que Do Until para los conjuntos de registros. Obtendremos las propiedades y el estado de cada nodo.

      For Each objNode In colNodes
        WScript.Echo "  Node: " & objNode.Name
        WScript.Echo "    Number of Processors: " & objNode.NumberOfProcessors
        WScript.Echo "    Processor Architecture: " & _
         objNode.ProcessorArchitecture
        WScript.Echo "    Processor Speed: " & objNode.ProcessorSpeed & " MHz"
        WScript.Echo "    Memory: " & objNode.Memory & " MB"
        strStatus = ""
        Select Case objNode.Status
          Case 0 strStatus = "Ready"
          Case 1 strStatus = "Paused"
          Case 2 strStatus = "Unreachable"
          Case 3 strStatus = "Pending Approval"
          Case Else strStatus = "Status unobtainable"
        End Select
        WScript.Echo "    Status: " & strStatus
      Next

Para conocer cómo funciona este componente de la API de CCP, consulte La vuelta al nodo en 80 secuencias de comandos: un magnífico paseo por la biblioteca de secuencias de comandos de Compute Cluster Server (puede estar en inglés).

La estructura de esta secuencia de comandos se parece un poco a la del sistema solar. Hay un gran objeto clúster girando en torno a un conjunto de registros y pequeños objetos nodos en torno a cada clúster. Y, sin embargo, se mueve. Si Galileo pudiera ver esta secuencia de comandos, pensaría que ha muerto y ha ido al... bueno, adonde vayan los astrónomos herejes.

Por tanto, si está preparado para el gran salto, copie esta secuencia de comandos en el portapapeles y péguela en un archivo de texto, que deberá guardar con la extensión ".vbs". Asegúrese de pegar el nombre real de su dominio o contenedor en lugar de "CN=computers,DC=fabrikam,DC=com". A continuación vaya al símbolo del sistema y déle caña. Y sólo a modo de recordatorio: si aún no ha cambiado el host de secuencias de comandos predeterminado a Cscript.exe, puede ejecutar la secuencia de comandos en modo por lotes anteponiendo "cscript" a su nombre:

cscript findclusters.vbs

Éste es el código completo:

Lista: buscar clústeres en contenedor de Active Directory y obtener información.

'List all computers in container running Compute Cluster Server and get 
'information on nodes of each.

On Error Resume Next

'Initialize constants and variables.
Const ADS_SCOPE_SUBTREE = 2
strContainer = "CN=computers,DC=fabrikam,DC=com" 'Accessible AD container.
strObjectCategory = "ServiceConnectionPoint" 'For CCS
strServiceClassName = "MicrosoftComputeCluster"

'Search ADsPath recursively for compute clusters with ADO.
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = ("ADsDSOObject")
objConnection.Open "Active Directory Provider"
objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
objCommand.Properties("Sort On") = "cn"
'Construct SQL query.
objCommand.CommandText = _ 
 "SELECT serviceClassName,servicednsname FROM 'LDAP://" & _
 strContainer & "' " & _
 "WHERE objectCategory = '" & strObjectCategory & "' " & _
 "AND serviceClassName = '" & strServiceClassName & "'"
'Perform search of container.
Set objRecordSet = objCommand.Execute
If Err Then
  HandleError "ERROR: Unable to find container: " & strContainer
  WScript.Quit
End If
WScript.Echo "Searching AD container: " & strContainer & " ..."

'Create object reference to CCP API.
Set objComputeCluster = CreateObject("Microsoft.ComputeCluster.Cluster")
If Err Then
  HandleError "ERROR: Unable to find Compute Cluster Pack API " & _
   "on this computer. Cluster and node settings not available."
End If

'Check if returned record set is empty.
If Not objRecordSet.EOF Then
  objRecordSet.MoveFirst 
'Loop through compute clusters returned by query.
  Do Until objRecordSet.EOF
    strClusterDnsName = objRecordSet.Fields("servicednsname").Value
    Wscript.Echo vbCrLf & "Cluster DNS Name: " & strClusterDnsName
'Parse cluster name from DNS name.
    strClusterName = Left(strClusterDnsName, _
     (InStr(strClusterDnsName, ".") - 1))
    Wscript.Echo "Cluster Host Name: " & strClusterName
    
'Connect to cluster head node and get cluster properties.
    objComputeCluster.Connect(strClusterName)
    If Err Then
      HandleError "ERROR: Unable to connect to this compute cluster."
    Else
      WScript.Echo "Compute Cluster Name: " & objComputeCluster.Name
      WScript.Echo "Server calls asynchronous: " & _
       objComputeCluster.IsAsynchronous
      WScript.Echo "Compute Cluster Environment Variables:"
      Set colEnvVars = objComputeCluster.EnvironmentVariables
      For Each objEnvVar In colEnvVars
        WScript.Echo "  " & objEnvVar.Name & " = " & objEnvVar.Value
      Next
      WScript.Echo "Compute Cluster Parameters:"
      Set colParams = objComputeCluster.Parameters
      For Each objParam In colParams
        WScript.Echo "  " & objParam.Name & " = " & objParam.Value
      Next
      WScript.Echo "Compute Cluster Nodes:"
      Set colNodes = objComputeCluster.ComputeNodes
'Loop through nodes and get node properties.
      For Each objNode In colNodes
        WScript.Echo "  Node: " & objNode.Name
        WScript.Echo "    Number of Processors: " & objNode.NumberOfProcessors
        WScript.Echo "    Processor Architecture: " & _
         objNode.ProcessorArchitecture
        WScript.Echo "    Processor Speed: " & objNode.ProcessorSpeed & " MHz"
        WScript.Echo "    Memory: " & objNode.Memory & " MB"
        strStatus = ""
        Select Case objNode.Status
          Case 0 strStatus = "Ready"
          Case 1 strStatus = "Paused"
          Case 2 strStatus = "Unreachable"
          Case 3 strStatus = "Pending Approval"
          Case Else strStatus = "Status unobtainable"
        End Select
        WScript.Echo "    Status: " & strStatus
      Next
    End If

    objRecordSet.MoveNext 
  Loop 

Else
  Wscript.Echo "No records found."
End If

'******************************************************************************

Sub HandleError(strMessage)
'Handle errors passed from other parts of script.

strError = VbCrLf & VbCrLf & strMessage & _
 VbCrLf & "Number (dec) : " & Err.Number & _
 VbCrLf & "Number (hex) : &H" & Hex(Err.Number) & _
 VbCrLf & "Description  : " & Err.Description & _
 VbCrLf & "Source       : " & Err.Source
WScript.Echo strError
Err.Clear

End Sub

Por cierto, si desea secuencias de comandos más simplificadas, encontrará una versión reducida de esta secuencia de comandos, sin comentarios ni control de errores, en la sección sobre nodos del área Compute Cluster Server, en el Repositorio de secuencias de comandos.

Estampida de clústeres

Si tiene que administrar una gran cantidad de clústeres de cálculo, podría usar una secuencia de comandos como la que acabamos de analizar con objeto de establecer una lista de clústeres y nodos de referencia; sólo debe modificarla para que almacene la lista en un archivo de texto, hoja de cálculo o base de datos (consulte la función WriteTextFile en "Hay que tener hercios: preparación para la implementación de Compute Cluster Server con secuencias de comandos. Parte 2", que puede estar en inglés). De este modo, podrá ejecutar la secuencia de comandos periódicamente como una tarea programada e imprimir la lista de clústeres y nodos en ejecución en un momento dado. No sería difícil escribir una nueva secuencia de comandos que comparara ambas listas, registrara cualquier diferencia e informara de ello a los administradores. Podría capturar clústeres y nodos bloqueados o sin conexión, así como clústeres y nodos invasores agregados de manera no oficial.

Dr. Scripto: Si no es tan difícil, ¿por qué no la escribió?

Pensándolo bien, mientras se ausenta para comprobar los clústeres de cálculo de su equipo, no resultaría mucho más costoso ampliar la secuencia de comandos para que supervise las condiciones de cada clúster y nodo con la API de CCP y otras tecnologías de secuencias de comandos como el Instrumental de administración de Windows (WMI). Pero eso es harina de otro costal.

Si es desarrollador (o creador de secuencias de comandos con experiencia) y está familiarizado con .NET Framework (o le gustaría estarlo), en el blog para desarrolladores de Dennis Crain encontrará una versión equivalente en código C# para buscar clústeres de cálculo en un directorio: "Lectura de nombres de nodos de cabeza en clústeres de cálculo", en el sitio de Windows HPC Community (que puede estar en inglés).

Recursos

Compute Cluster Server y Active Directory

Implementación y administración de Microsoft Windows Compute Cluster 2003 (puede estar en inglés)

Requisitos de red para clústeres de cálculo (puede estar en inglés)

Objetos de datos ActiveX ( ADO )

Secuencias de comandos para bases de datos (puede estar en inglés)

Microsoft Windows 2000 Scripting Guide: trabajo con bases de datos (puede estar en inglés)

SDK de objetos de datos ActiveX de Microsoft (ADO)

Amigo, ¿dónde está mi impresora?: uso de secuencias de comandos para realizar una búsqueda en Active Directory (puede estar en inglés)

Interfaces de servicio de Active Directory (ADSI, Active Directory Service Interfaces)

Secuencias de comandos para Active Directory (puede estar en inglés)

Microsoft Windows 2000 Scripting Guide: manual sobre secuencias de comandos ADSI (puede estar en inglés)

SDK de interfaces de servicio de Active Directory (puede estar en inglés)

API de Compute Cluster Pack

La vuelta al nodo en 80 secuencias de comandos: un magnífico paseo por la biblioteca de secuencias de comandos de Compute Cluster Server (puede estar en inglés)

Repositorio de secuencias de comandos: Compute Cluster Server (puede estar en inglés)

SDK de Microsoft Compute Cluster Pack (puede estar en inglés)