miércoles, 30 de mayo de 2012

Fallo en la instalación del cliente de SCCM

Un par de servidores no reportaban inventario de hardware.
La solución en este caso es bastante drástica, pero por lo general, muy efectiva.

  • Desinstalar el agente de SCCM (ccmsetup.exe /uninstall)
  • Renombrar la carpeta Repository que se encuentra en C:\Windows\System32\WBEM para que Windows regenere el repositorio WMI
  • Reinstalar el cliente. 


Por lo general esta serie de pasos soluciona los problemas con el cliente que generan la ausencia de inventarios de hardware. Sin embargo, muchas veces, y sin que todavía haya encontrado una explicación al asunto, la instalación del cliente simplemente falla.
 En el log de instalación (C:\Windows\System32\CCMSetup\CCMsetup.log) encontramos este mensaje: 

Failed to create the ccmsetup service (0)

Y el mensaje no puede ser más claro. No puede crearse un servicio de Windows para el ejecutable CCMSetup.exe. La solución es muy sencilla entonces, hay que hacer que el instalador se ejecute como un proceso aislado y no como un servicio, y para ello contamos con el parámetro NoService.
Así que simplemente ejecutamos el instalador del cliente de este modo:

CCMSetup.exe /NoService

Y voila!, el cliente de SCCM se instala sin inconvenientes.

lunes, 28 de mayo de 2012

Balancear maquinas virtuales en un cluster con PowerShell

Otro Offtopic, pero no podía dejar de publicar este script de Powershell que hice para distribuir las virtuales en un cluster.
Primero vale aclarar que mis conocimientos de PowerShell son mínimos, y es un lenguaje que me resulta muy difícil de entender y aprender. Vengo del mundo de la programación dura y estructurada, y PowerShell se toma demasiadas "licencias" para mi gusto, por lo que me resulta difícil entender su comportamiento muchas veces.
Aún así hice este sencillo script cuya tarea es bastante simple. Lo que hace es contar el número de maquinas virtuales en un cluster y distribuirlas entre todos los nodos. El "balanceo" no tiene en cuenta recursos, ni nada parecido, es simplemente un conteo de virtuales, pero en mi caso y dentro de nuestra infraestructura resulta bastante útil.

Aquí el script:


Import-Module FailoverClusters

$Cluster=""

$Cluster = Read-Host "Indique nombre del cluster"

$Total=(Get-ClusterResource -cluster $Cluster | where {$_.resourcetype.name -eq "Virtual Machine"}).Count

$Nodos=Get-ClusterNode -cluster $Cluster

$CantNodos=(Get-ClusterNode -cluster $Cluster).count

Write-host "El cluster $Cluster tiene un total de $Total maquinas virtuales a distribuir en $CantNodos nodos."

$Promedio=[MATH]::ROUND($Total/$CantNodos)

Write-host "En total debería haber $Promedio maquinas virtuales por nodo."

Foreach ($Nodo in $Nodos)

{

    $PorNodo=(Get-ClusterNode $Nodo.Name -cluster $Cluster | Get-ClusterResource | where {$_.resourcetype.name -eq "Virtual Machine"}).count

    Write-Host "El nodo $Nodo tiene $PorNodo maquinas virtuales"

    if ($PorNodo -gt $Promedio)

        {

        $Diferencia=$PorNodo-$Promedio

        Write-Host "Se debe mover $Diferencia maquina/s virtual/es del nodo $Nodo"

        for($i=1; $i -le $Diferencia; $i++)

            {

            Foreach ($Nodo1 in $Nodos)

                {

                $PorNodo1=(Get-ClusterNode $Nodo1.Name -cluster $Cluster | Get-ClusterResource | where {$_.resourcetype.name -eq "Virtual Machine"}).count

                if ($PorNodo1 -lt $Promedio)

                    {

                        $Maquina=Get-ClusterNode $Nodo.Name -cluster $Cluster | Get-ClusterResource | where {$_.resourcetype.name -eq "Virtual Machine"} | Select-object -first 1

                        Write Host "Se procede a mover la maquina virtual $Maquina"

                        Move-ClusterVirtualMachineRole -Name $Maquina.OwnerGroup -Cluster $Cluster -node "$Nodo1"
                        Break

                    }

                }

            }

        }



}


Como dije, no soy experto en PowerShell, y estoy seguro de que esto puede hacerse mejor, más fácil y con menos líneas de código. Pero esto funciona y lo hace muy bien.

Las máquinas virtuales se mueven utilizando LiveMigration, así que el uso del script no implica corte de servicios, y solo es válido en cluster de Hyper-V 2008 R2.

viernes, 27 de abril de 2012

Script para enviar alertas por falta de inventario de hardware

En el post anterior veíamos como generar un reporte que nos liste las computadoras que en determinada cantidad de días no enviaron su inventario de hardware al servidor.
En esta ocasión veremos como armar un sencillo script que envía un correo con el reporte que hicimos antes.
El mismo script puede usarse para enviar cualquier otro reporte de SCCM. Si además combinamos este script con una tarea programada de Windows podremos tener alertas periódicas con datos sobre las computadoras que administramos con SCCM.

Este es el script:

Remitente="correo del remitente"
Destinatario="correo del destinatario"
Asunto= "Asunto del correo"

'1 para SMTP local, 2 para SMTP remoto
TipoSMTP = 2 

'Dirección del servidor SMTP
SMTP = "dirección o IP de nuestro servidor SMTP"

'Puerto SMTP utilizado por nuestro servidor
Puerto = 25

'URL del reporte que enviaremos por correo
Reporte = "http://hellboy/Reportes/Report.asp?ReportID=431&Dias=2&SortRs1Col=3&SortRs1Dir=2"


'************************Envío del correo***************************************

Set objMessage = CreateObject("CDO.Message")
Set Stm = CreateObject("ADODB.Stream")


objMessage.Subject = Asunto
objMessage.From = Remitente
objMessage.To = Destinatario

objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/sendusing") = TipoSMTP
'Servidor SMTP
objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserver") = SMTP
'Puerto SMTP
objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = Puerto

objMessage.CreateMHTMLBody(Reporte)
'ObjMessage.AddAttachment (Adjunto)
objMessage.Configuration.Fields.Update

On Error Resume Next  
objMessage.Send
If not(Err.Number = 0) Then  
    MsgBox Err.Description, vbCritical, " Error al enviar el mail "  
End If

Así de simple.
En este caso el script envía el reporte que creamos en nuestro anterior post (el que buscaba computadoras sin inventario de hardware reciente), y le pasa como parámetro (dentro de la URL) la cantidad de días límite para la búsqueda (en este caso 2 días).
Para enviar cualquier otro reporte basta con ejecutarlo en el SCCM y copiar la URL dentro del script.
Para que las alertas lleguen periodicamente basta con crear una tarea programada que ejecute el script.

Saludos
Franco

miércoles, 25 de abril de 2012

Reporte con computadoras que no envían inventario de hardware durante X días

En un post anterior vimos la manera de armar una colección con clientes que no enviaban su inventario de hardware durante un tiempo determinado.
En este caso haremos algo parecido, pero con un reporte. La diferencia aquí es que al reporte le daremos como parámetro el número de días mínimo para que una computadora se considere que está fallando en su inventario.

La idea de tener un reporte de este tipo, además de la colección antes vista, es que este dato también pueda ser visto por usuarios que no tienen acceso a la consola, tal como puede ser personal de soporte técnico o seguridad.

La consulta en este caso es bastante sencilla. Se trata de una query con un único prompt y que utiliza la función DATEDIFF para obtener la cantidad de días desde el último inventario agregado a la base de datos.


SELECT     sys.Netbios_Name0 AS Servidor,
WS.LastHWScan AS [Último escaneo de HW],
DATEDIFF(day, WS.LastHWScan, GETDATE()) AS [Días desde el último escaneo]
FROM
v_GS_WORKSTATION_STATUS AS WS
INNER JOIN
v_R_System AS sys
ON sys.ResourceID = WS.ResourceID
WHERE  
(DATEDIFF(day, WS.LastHWScan, GETDATE()) > @dias)

Tan simple como eso. El resultado se verá más o menos así:

Saludos
Franco

lunes, 23 de abril de 2012

No funciona el inventario de hardware

En el anterior post veíamos la manera de armar una colección con todos los equipos que no reportan un inventario de hardware desde hace 30 días. Por lo general la razón para que el inventario de hardware no funcione se encuentra del lado del cliente. Problemas con el servicio de WMI, falta de espacio en disco, problemas de comunicación con el servidor, certificados, etc.
Pero si empezamos a notar que son muchas las computadoras que no reportan su inventario de hardware, entonces podemos estar ante un problema del lado del servidor, o para ser más precisos, un problema en la manera en que el cliente y el servidor se comunican para trasmitir la información del inventario de hardware.

El circuito del inventario de hardware

La información colectada por el cliente es empaquetada en un archivo MIF (Management Information Format).   Estos archivos son enviados por el cliente al servidor utilizando el servicio de transferencia en segundo plano (BITS). El servidor analiza cada uno de los MIFs recibidos, y si no hay ningún error agrega la información a la base de datos. En caso de error, el MIF es enviado a la carpeta BADMIFS, para que puedan ser analizados en busca del problema.

Errores en los MIFs

Muchas veces, los errores que impiden el procesamiento de un MIF son temporales. Algún valor faltante, información mal colectada, errores de formato, etc. Pero a veces se trata de errores que se repiten cada vez que el cliente envía información al servidor. Un ejemplo de este tipo de problemas son los archivos MIF demasiado grandes.

Cuando el tamaño importa

Si vamos a Site Settings/Client Agents/Hardware Inventory Client Agent, en el cuadro de diálogo que se abre, en la pestaña General, encontraremos la opción de  Maximum custom MIF file size (KB), dónde podremos especificar el valor máximo del archivo MIF a importar. El valor más grande admitido aquí es de 5120 KB, es decir 5 MB.


Si entramos a la carpeta C:\Program Files\Microsoft Configuration Manager\inboxes\auth\dataldr.box\BADMIFS, allí podremos ver todos los MIFS rechazados. En la vista Detalles de Windows, observaremos el tamaño de los archivos. Si este tamaño supera el establecido en el cuadro de diálogo mostrado anteriormente, los MIFS serán siempre rechazados y la información de inventario nunca pasará a la base de datos.

Por encima del límite

Si ninguno de los MIFs rechazados supera los 5MB que tiene como límite máximo el SCCM, entonces la solución a este problema consiste sencillamente en modificar la configuración establecida en la consola.
El problema es cuando nuestros MIFs superan los 5 MB, entonces deberemos recurrir a una modificación de la configuración de nuestro servidor un tanto más rústica.
Abrimos el editor de registro y buscamos la clave HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SMS\Components\SMS_INVENTORY_DATA_LOADER\Max MIF Size. Modificamos su valor en decimal y establecemos el tamaño límite máximo para los MIFs en bytes.


El riesgo de los MIFs grandes

No es difícil suponer porque Microsoft decidió establecer un valor máximo para los MIFs a procesar. Cada MIF de un cliente debe transitar por nuestra red, almacenarse en nuestro servidor, y luego ser procesado, parseado y almacenado en nuestra base de datos. En una organización con 5000 clientes, establecer un MIF de 5 MB representa 24 GB de información saturando la red y ocupando espacio en disco y procesamiento de nuestros servidores.
Lo ideal, cuando nuestros MIFs crecen sin control, es empezar a limitar el inventario, reduciendo los items a recolectar. Para hacer esto deberemos modificar el tan temido y conocido SMS_DEF.MOF, del que hablaremos en otra oportunidad.

Saludos
Franco

jueves, 19 de abril de 2012

Colección de computadoras que no se reportan hace 30 días

El escaneo de hardware o Hardware Inventory es sin lugar a dudas una de las funciones más importantes del SCCM. En la mayoría de los casos, suele ser este inventario el que se realiza con mayor frecuencia, y el que nos marca la pauta de un cliente funcionando correctamente o no.
Existen reportes en el SCCM con los que fácilmente podremos buscar todos los equipos que no hayan enviado un inventario de hardware en los últimos días ¿pero que tal si nos interesa tener esos equipos en una colección?
De este modo podríamos tomar acciones de remediación en forma conjunta, o podemos hacerlo por el simple hecho de tener siempre a mano la lista de esos clientes problemáticos que nos veremos obligados a reparar.

Para armar una colección de este tipo no podremos utilizar el asistente de SCCM, sino que necesitaremos escribir la query en WQL dentro del cuadro de diálogo correspondiente. La consulta para esta colección quedaría así entonces:

select

SMS_R_SYSTEM.ResourceID,

SMS_R_SYSTEM.ResourceType,

SMS_R_SYSTEM.Name,

SMS_R_SYSTEM.SMSUniqueIdentifier,

SMS_R_SYSTEM.ResourceDomainORWorkgroup,

SMS_R_SYSTEM.Client

from SMS_R_System  inner join

SMS_G_System_WORKSTATION_STATUS

on SMS_G_System_WORKSTATION_STATUS.ResourceID = SMS_R_System.ResourceId

where SMS_G_System_WORKSTATION_STATUS.LastHardwareScan <=  DateAdd(dd,-30,GetDate())


Para modificar el tiempo mínimo desde el último reporte deben cambiar el valor al final de al consulta, dentro de  DateAdd(dd,-30,GetDate()). En este caso está configurado en 30 días, pero es posible asignar cualquier otro valor según sea necesario.

El resultado es una colección con clientes a los que deberemos echar una mirada.

Saludos
Franco

Colección para maquinas virtuales

Hoy una query sencillita, pero que puede resultar bastante útil. En este caso armaremos una colección dinámica poblada exclusivamente por maquinas virtuales.

La query para la colección sería esta:

select 
SMS_R_SYSTEM.ResourceID,
SMS_R_SYSTEM.ResourceType,
SMS_R_SYSTEM.Name,
SMS_R_SYSTEM.SMSUniqueIdentifier,
SMS_R_SYSTEM.ResourceDomainORWorkgroup,
SMS_R_SYSTEM.Client 
from SMS_R_System inner join 
SMS_G_System_COMPUTER_SYSTEM 
on SMS_G_System_COMPUTER_SYSTEM.ResourceId = SMS_R_System.ResourceId 
where SMS_G_System_COMPUTER_SYSTEM.Model in 
("Virtual Machine","VMware Virtual Platform")

En este caso agrupamos en la misma colección las maquinas virtuales creadas con software de Microsoft ("Virtual Machine") y aquellas que utilizan VMWare ("VMWare Virtual Platform").

Esta consulta puede armarse usando el asistente del SCCM, y no reviste mayor complejidad.



Del mismo modo, puede usarse una query similar, pero negando el operador "IN" para encontrar todas las computadoras que no son virtuales, las "físicas", por llamarlas de algún modo.

select 
SMS_R_SYSTEM.ResourceID,
SMS_R_SYSTEM.ResourceType,
SMS_R_SYSTEM.Name,
SMS_R_SYSTEM.SMSUniqueIdentifier,
SMS_R_SYSTEM.ResourceDomainORWorkgroup,
SMS_R_SYSTEM.Client 
from SMS_R_System inner join 
SMS_G_System_COMPUTER_SYSTEM 
on SMS_G_System_COMPUTER_SYSTEM.ResourceId = SMS_R_System.ResourceId 
where SMS_G_System_COMPUTER_SYSTEM.Model NOT IN 
("Virtual Machine","VMware Virtual Platform")

Como siempre que armamos colecciones dinámicas, es importante no olvidar crear un schedule para la actualización de los recursos, y en el caso de SCCM 2007 R3, tildar la opción para agregar recursos dinámicamente.

Saludos
Franco