Trickle Feed script update - Direct Memberships and Moves to reduce repeat instances
Their is another script out in the Code Repository of MyITForum.com.
10762Tricle_Feed.zip
The orginal script uses queries and grabs a random (possibly repeating) number of clients from a source collection. Then adds that query to the destination collection. This works well when you do large number of machines... but does not work so well on smaller groups.
My version attached and below:
- Does Direct Memberships
- Outputs to a log to check whats going on
- Takes a Source Collection with PCs added (assumes machine names are instance names)
- Grabs Total # of machines / divides by number you want to move at a time = #
- Takes the calculated # (in above step) machine each to not make it random but evenly dispersed
- Adds those machine names as direct membership rules in destination collection
'Script Updated by Shaun Cassells 11072006
'scassells at aegonusa.com
'**************************************************************************************
' Add scheduled task on server to run script every 30 minutes!
' Prompts for
' SMS Server
' SMS Site Code
' Number of machines to be moved per call
' Source Collection
' Destination Collection
'**************************************************************************************
Option Explicit
Dim SourceCollection, SourceCollectionID, DestinationCollection, DestinationCollectionID
Dim SMSSiteServerName, SMSSiteCode, MaximumMachinePerInterval
Dim instCollection, instDirectRule, objArgs
Dim objLocator, objSMS, objEnumerator, strQuery, instance, instances, objNameDictionary, objResrouceIDDictionary
err.clear
set objArgs = WScript.Arguments
'Read in Input
If objArgs.Count <> 5 Then
WScript.Echo "Missing arguements" & VbCrLf &_
"Please pass Two Collection Names (in quotes)" & VbCrLf &_
" The SMS Server Name " & VbCrLf & _
" The Site Code " & VbCrLf & _
" # of machines to be migrated at each interval " & VbCrLf & _
" The Source Collection Name " & VbCrLf & _
" The Destination Collection Name "
WScript.Quit
Else
SMSSiteServerName = ObjArgs(0)
SMSSiteCode = ObjArgs(1)
MaximumMachinePerInterval = ObjArgs(2)
SourceCollection = ObjArgs(3)
DestinationCollection = ObjArgs(4)
End If
FileAddLineToLogFile "************************************************************************************************************************"
FileAddLineToLogFile " " & Date & " " & Time & " *******************************************************************************"
FileAddLineToLogFile "************************************************************************************************************************"
FileAddLineToLogFile "Starting Script"
FileAddLineToLogFile "MaximumMachinePerInterval = " & MaximumMachinePerInterval
FileAddLineToLogFile "SourceCollection = " & SourceCollection
FileAddLineToLogFile "DestinationCollection = " & DestinationCollection
FileAddLineToLogFile "SMSSiteServerName = " & SMSSiteServerName
FileAddLineToLogFile "SMSSiteCode = " & SMSSiteCode
FileAddLineToLogFile "connect to scripting WMI interface"
Set objLocator = CreateObject("WbemScripting.SWbemLocator")
FileAddLineToLogFile "Connect to the server and Name space"
set objSMS=objLocator.ConnectServer(SMSSiteServerName, "root\sms\site_" & SMSSiteCode)
FileAddLineToLogFile "set the security level to use impersonation"
objSMS.Security_.ImpersonationLevel = 3
FileAddLineToLogFile "Get the SourceCollection contents"
strQuery = "select CollectionID, Name from SMS_Collection where (Name in ('" & SourceCollection & "', '" & DestinationCollection & "'))"
Set instances = objSMS.ExecQuery(strQuery)
If instances.Count <> 2 Then
FileAddLineToLogFile "Collection Name ID lookup failed on one of the 2"
Wscript.QUIT
Else
Dim CountInstance
For Each instance In instances
Select Case instance.Name
Case SourceCollection
SourceCollectionID = instance.CollectionID
Case DestinationCollection
DestinationCollectionID = instance.CollectionID
End Select
Next
End If
FileAddLineToLogFile "SourceCollectionID = " & SourceCollectionID
FileAddLineToLogFile "DestinationCollectionID = " & DestinationCollectionID
FileAddLineToLogFile "Create Dictionary Object"
Set objNameDictionary = CreateObject("Scripting.Dictionary")
Set objResrouceIDDictionary = CreateObject("Scripting.Dictionary")
Dim objDicItem, TotalSourceCollection, InstancestoPull, PositionDictionary
FileAddLineToLogFile "************************************************************************************************************************"
FileAddLineToLogFile "Pull The Collection contents machine Names"
strQuery = "SELECT Name, ResourceID FROM SMS_CM_RES_COLL_" & SourceCollectionID
FileAddLineToLogFile strQuery
Set objEnumerator = objSMS.ExecQuery(strQuery)
FileAddLineToLogFile "Now we have all of the system Names and ResouceIDs in a Dictionary Object;"
For Each instance In objEnumerator
FileAddLineToLogFile instance.Name
FileAddLineToLogFile instance.ResourceID
Next
FileAddLineToLogFile "************************************************************************************************************************"
TotalSourceCollection = objEnumerator.Count
FileAddLineToLogFile "TotalSourceCollection = " & TotalSourceCollection
'Round to the nearest whole number
InstancestoPull = round((TotalSourceCollection / MaximumMachinePerInterval), 0)
FileAddLineToLogFile "MaximumMachinePerInterval = " & MaximumMachinePerInterval
'If value is less than 1 that means pull all remaing values
If InstancestoPull < 1 Then
InstancestoPull = 1
End If
FileAddLineToLogFile "InstancestoPull = " & InstancestoPull
CountInstance = 0
PositionDictionary = 0
FileAddLineToLogFile "************************************************************************************************************************"
FileAddLineToLogFile "Get Values out into Dictionary Objects"
For Each instance in objEnumerator
FileAddLineToLogFile "CountInstance mod InstancestoPull = " & (CountInstance mod InstancestoPull)
FileAddLineToLogFile "CountInstance = " & CountInstance
FileAddLineToLogFile "InstancestoPull = " & InstancestoPull
If (CountInstance mod InstancestoPull) = 0 Then
'-------------------------------------------------------------------
'Get the Values and add to the Dictionary
FileAddLineToLogFile instance.Name & " at place " & CountInstance
objNameDictionary.Add PositionDictionary, instance.Name
objResrouceIDDictionary.Add PositionDictionary, instance.ResourceID
PositionDictionary = PositionDictionary + 1
End If
CountInstance = CountInstance + 1
Next
FileAddLineToLogFile "************************************************************************************************************************"
FileAddLineToLogFile "Time to remove objects out of SourceCollection"
FileAddLineToLogFile "Connect to the Source Collection = " & SourceCollection
FileAddLineToLogFile "Connect to the Source CollectionID = " & SourceCollectionID
Set instCollection = objSMS.Get("SMS_Collection.CollectionID=""" & SourceCollectionID & """")
FileAddLineToLogFile "Connect to the Direct Rule Source"
FileAddLineToLogFile "************************************************************************************************************************"
For Each objDicItem In objNameDictionary
FileAddLineToLogFile "Remove Machine ResourceID from Source Collection = " & UCase(objResrouceIDDictionary.Item(objDicItem))
Set instDirectRule = objSMS.Get("SMS_CollectionRuleDirect").SpawnInstance_
instDirectRule.ResourceID = UCase(objResrouceIDDictionary.Item(objDicItem))
instCollection.DeleteMembershipRule instDirectRule
Next
FileAddLineToLogFile "Initiate a Refresh of Source Collection ONLY"
instCollection.RequestRefresh False
FileAddLineToLogFile "************************************************************************************************************************"
FileAddLineToLogFile "Free the Query from memory"
Set objEnumerator = Nothing
Set instDirectRule = Nothing
Set instCollection = Nothing
FileAddLineToLogFile "************************************************************************************************************************"
FileAddLineToLogFile "Now we have all of the system Names and ResouceIDSin a Dictionary Object;"
For Each objDicItem In objNameDictionary
FileAddLineToLogFile UCase(objNameDictionary.Item(objDicItem))
FileAddLineToLogFile UCase(objResrouceIDDictionary.Item(objDicItem))
Next
FileAddLineToLogFile "************************************************************************************************************************"
FileAddLineToLogFile "Connect to the Destination Collection = " & DestinationCollection
FileAddLineToLogFile "Connect to the Destination CollectionID = " & DestinationCollectionID
set instCollection = objSMS.Get("SMS_Collection.CollectionID=""" & DestinationCollectionID & """")
FileAddLineToLogFile "Connect to the Direct Rule"
For Each objDicItem in objNameDictionary
Set instDirectRule = objSMS.Get("SMS_CollectionRuleDirect").SpawnInstance_
instDirectRule.ResourceClassName = "SMS_R_System"
instDirectRule.ResourceID = UCase(objResrouceIDDictionary.Item(objDicItem))
FileAddLineToLogFile "Adding ResourceID = " & instDirectRule.ResourceID
instDirectRule.RuleName = UCase(objNameDictionary.Item(objDicItem))
FileAddLineToLogFile "Adding RuleName = " & instDirectRule.RuleName
instCollection.AddMembershipRule instDirectRule
FileAddLineToLogFile "Adding Direct Rule"
Next
FileAddLineToLogFile "Initiate a Refresh of this Destination Collection ONLY"
instCollection.RequestRefresh False
FileAddLineToLogFile "************************************************************************************************************************"
FileAddLineToLogFile "Empty variables from memory"
Set instDirectRule = Nothing
Set instCollection = Nothing
Set objSMS = Nothing
Set objLocator = Nothing
Set objArgs = Nothing
FileAddLineToLogFile "Notify user of script completion"
'**************************************************************************************************************
Sub FileAddLineToLogFile (DataToAdd)
'Function
'Add a log entry to where the current script is located with extention of .log
'Input
'Data to be added to the log
'Output
'Log file in script directory contains the new log entry
on error resume next
Const ForAppending = 8
Dim objFSO, objLogFile, LogFileName
Set objFSO = CreateObject("Scripting.FileSystemObject")
LogFileName = wscript.scriptfullname & ".log"
Set objLogFile = objFSO.OpenTextFile ( LogFileName, ForAppending, True)
'Write the Data
objLogFile.WriteLine Date & " " & Time & " " & DataToAdd
'Close the file
objLogFile.Close
End Sub