[CmdletBinding(DefaultParametersetName='None')] Param ( #Config switches [Parameter()][switch]$RunLocal, #Run WHAM without a dependancy on the media servers - this requires all files to be downloaded to $ENV:TMP first [Parameter()]$FolderName, #Name of the WHAM root folder [Parameter()]$JobLimit = 15, #Number of concurrent jobs the script will create (15 is default) [Parameter()]$ScriptTimeout = 60, #default time out of script jobs [Parameter()][switch]$ShowMenu, #Show the user menu [Parameter()][switch]$Dev, #Disable logging [Parameter()][switch]$DisableConfirmation, #Disable the prompt for you have selected servers/templates [Parameter()][switch]$NoLogging, #Disable logging to appstats and CSV file #Connection test switches [Parameter()][switch]$SkipTests, #skip connection testing [Parameter()][switch]$SkipCoreStatus, #always run on servers regardless of core status [Parameter()][switch]$ContinueOnPingError, #this is done by default now #Template switches [Parameter()]$TemplateName, #the name of the template to preselect #work in progress -> $TemplateName = "Set-DNSServers -NICName Public -DNSServers 8.8.8.8,8.8.4.4","Disable-ServiceRS -Servicename BITS" -WithParams [Parameter()]$CustomScriptblock, #scriptblock to run directly on machine bypassing the template functions - see wiki for how to use this [Parameter()][switch]$TemplateQC, #when importing templates, look in the QC folder instead of Live [Parameter()][switch]$TemplateDev, #when importing templates, look in the DEV folder instead of Live #Input switches - used to get devices from CORE [Parameter()][string]$ticketnum, #ticketnumber to pull devices for [Parameter()]$devices, #Comma seperated (or array) of device lists to pull from CORE [Parameter()][string]$account, #Account number for devices [Parameter()][array]$Computers, #array of computer devices, use Powershell CoreCTK format (Get-CoreDevice) #output switches [Parameter()][switch]$ReturnDataObject, #Returns the computer object with all results at the end of the script #Credential switches - used to pass credentials through [Parameter(ParameterSetName='DomainCred',Mandatory=$true)]$DomainUSer, [Parameter(ParameterSetName='DomainCred',Mandatory=$true)]$DomainPass, [Parameter(ParameterSetName='IntCred',Mandatory=$true)]$IntensiveUser, #Specify intensive credentials (use when supplying the computer object as you will not be prompted) [Parameter(ParameterSetName='IntCred',Mandatory=$true)]$IntensivePass, #Specify intensive credentials (use when supplying the computer object as you will not be prompted) #I dont think this is used [Parameter()][string]$session #CORE Token ) #v2.0 - Menu, CLI and custom scriptblock support #v1.7 - Support for HTTPS media servers #v1.6 - CLI support, bug fixes #v1.5 - see wiki for change log http://rax.io/wham #v1.0 - full release #v0.0 - Initial build $Global:version = "2.0" write-verbose "version $Global:version" #Set global dev if($dev){$Global:Dev = $true} write-verbose "Dev $Global:Dev" #Set our WHAM root folder if not set when calling the script If ($FolderName){ $Global:FolderName = $FolderName } else{ $Global:FolderName = "WHAM" } #if we show the menu disable the confirmation if($ShowMenu){ $DisableConfirmation = $true } #Create our object used to track times $Time = New-Object PSObject -Property @{ ScriptStart = (Get-Date) ScriptFinish = "" TotalScript = "" DataGatheringStart = "" DataGatheringFinish = "" TotalDataGathering = "" TemplateStart = "" TemplateFinish = "" TotalTemplate = "" ConnectionTestJobStart = "" ConnectionTestJobFinish = "" TotalConnectionTestJob = "" ScriptJobStart = "" ScriptJobFinish = "" TotalScriptJob = "" } #Test Powershell version #Requires -version 3 if($RunLocal){ write-host "Running in local mode" if($dev){$VerbosePreference = "silentlycontinue"} Import-Module -DisableNameChecking "$ENV:TMP\WHAM_Data_Module.psm1" -Force -Scope Global Import-Module -DisableNameChecking "$ENV:TMP\WHAM_Template_Module.psm1" -Force -Scope Global Import-Module -DisableNameChecking "$ENV:TMP\WHAM_Execution_Module.psm1" -Force -Scope Global Import-Module -DisableNameChecking "$ENV:TMP\Media_Server_Functions.psm1" -Force -Scope Global Import-Module -DisableNameChecking "$ENV:TMP\Logging_Module.psm1" -Force -Scope Global Import-Module -DisableNameChecking "$ENV:TMP\Questions_Module.psm1" -Force -Scope Global Import-Module -DisableNameChecking "$ENV:TMP\CTKCore.psm1" -Force -Scope Global Import-Module -DisableNameChecking "$ENV:TMP\BBCode.psm1" -Force -Scope Global #Copy PSEXEC to $ENV:TMP else this wont work if($dev){$VerbosePreference = "continue"} }else{ $Modules = @( "Media/ScriptRepository/Powershell/Shared_Modules/Media_Server_Functions.psm1", "Media/ScriptRepository/Powershell/WHAM/Modules/WHAM_Data_Module.psm1", "Media/ScriptRepository/Powershell/WHAM/Modules/WHAM_Template_Module.psm1", "Media/ScriptRepository/Powershell/Shared_Modules/Logging_Module.psm1", "Media/ScriptRepository/Powershell/Shared_Modules/Questions_Module.psm1", "Media/ScriptRepository/Powershell/CTKCore/CTKCore.psm1", "Media/ScriptRepository/Powershell/WHAM/Modules/WHAM_Execution_Module.psm1" "Media/ScriptRepository/Powershell/BBCode/BBCode.psm1" ) Import-MediaServerModule $Modules -DC ORD #We download this module as we use it in the powershell jobs and need to import it later Download-MediaServerFile -URLPath "Media/ScriptRepository/Powershell/WHAM/Modules/WHAM_Execution_Module.psm1" -DC ORD Download-MediaServerFile -URLPath "Media/ScriptRepository/Powershell/WHAM/PSEXEC.exe" -DC ORD } If($ShowMenu){ $ReturnedMenuOutput = Show-Menu switch -regex ($ReturnedMenuOutput.DeviceInput) { #account "^\d{7,9}$" {$Account = $ReturnedMenuOutput.DeviceInput} #device list "^\d{6},\d{6}" {$Devices = $ReturnedMenuOutput.DeviceInput} #ticket "^\d{6}-\d{5}$" {$ticketnum = $ReturnedMenuOutput.DeviceInput} #account or device "^\d{6}$" { $IsDevice = Test-COREDevice -Device $ReturnedMenuOutput.DeviceInput if($IsDevice){ $Devices = $ReturnedMenuOutput.DeviceInput }else{ $Account = $ReturnedMenuOutput.DeviceInput } } Default {write-host "Could not parse input - script quitting" -ForegroundColor red ; break} } #Refresh our code token if we supply it (the form validates it and displays the RSAToken field if its not valid) if($ReturnedMenuOutput.RSAToken ){ $x = Get-CoreToken -RSAToken $ReturnedMenuOutput.RSAToken } $TemplateName = $Global:TemplateName #Save credentials $IntensiveUser = $ReturnedMenuOutput.IntensiveUser $IntensivePass = $ReturnedMenuOutput.IntensivePassword $DomainUser = $ReturnedMenuOutput.DomainUser $DomainPass = $ReturnedMenuOutput.DomainPassword $Global:MenuOutput = $null $Global:MenuOutput = $ReturnedMenuOutput } #Create WHAM folders needed for logging and output Set-WHAMFolderPaths If(-NOT $ShowMenu){ #Show our header Display-Header } #Check if we are running in QC mode If (($TemplateQC) -OR $TemplateDEV){ Write-host " " Write-host "WARNING: You are running WHAM in QC/DEV mode, templates presented here have not been fully tested" -ForegroundColor Yellow Write-host "WARNING: Proceed with caution" -ForegroundColor Yellow } #Run Data gathering module to get device data if not provided when script run If ($Computers.Length -eq 0) { $Time.DataGatheringStart = (Get-Date) If (($Account) -or ($devices) -or ($ticketnum)){ #create our param blob for calling the non interactive wham device function $Params = @{} If ($Account){$Params.Add("Account", $Account)} If ($devices){$Params.Add("devices", $devices)} If ($ticketnum){$Params.Add("ticketnum", $ticketnum)} $Output = Get-WHAMDevicesNI @Params }else{ #else call the normal function $Output = Get-WHAMDevices } $Computers = $Output.Computers #The array of computers from CORE $Ticketnum = $Output.ticketnum #ticket number entered by user (if option selected) if(-NOT $ShowMenu){ $intensiveUser = $Output.intensiveUser $intensivePass = $Output.intensivePass } $Time.DataGatheringFinish = (Get-Date) #check we got something back from CORE If ($Computers.Length -eq 0){ write-host "ERROR: Failed to get computers from CORE" -ForegroundColor Red break } } #Run Template module if scriptblock not provided when script run $Time.TemplateStart = (Get-Date) If ($CustomScriptblock) { #Call function that gets our scriptblock $Scriptblock = Get-WHAMScriptblock -Username $ENV:USERNAME -CustomScriptBlock $CustomScriptblock $FunctionSingleString = "Custom scriptblock" #$ScriptTimeout = $null #the total script timeout #$DownloadFile = $null #any download files names #$Collection = $null #if the template is a collection (for handling the output) }else{ #Create our blob of params $Params = @{} If ($TemplateName){$Params.Add("TemplateName", $TemplateName)} If ($TemplateQC){$Params.Add("QC", $true)} If ($Templatedev){$Params.Add("dev", $true)} #Call function that gets our scriptblock $WHAMTemplates = Get-WHAMScriptTemplate @Params $Scriptblock = $WHAMTemplates.Scriptblock #the scriptblock we will use to create the remote script $FunctionSingleString = $WHAMTemplates.FunctionSingleString #single string of the functions run to use for logging $ScriptTimeout = $WHAMTemplates.ScriptTimeout #the total script timeout $DownloadFile = $WHAMTemplates.DownloadFile #any download files names $Collection = $WHAMTemplates.Collection #if the template is a collection (for handling the output) } $Time.TemplateFinish = (Get-Date) #Confirm our user selected info list Write-SelectedDevices -computers $Computers Write-SelectedFunctions -ReturnedFunctions $($FunctionSingleString -split ",") If(-NOT $DisableConfirmation){ Write-Verbose "DisableConfirmation: $DisableConfirmation" Write-Host " " $Confirm = Ask-Question -Question "Are you sure (Y/N)" -ValidationArray "Y","N" -Default "Y" If (-NOT $Confirm){ write-host "User cancelled script, please rerun" -ForegroundColor Red break } } #Create file for the script $LocalScriptPath = "$Global:WHAMExportPath\WHAM-Script.ps1" New-ScriptFile -LocalScriptPath $LocalScriptPath -scriptblock $Scriptblock #Kill any old jobs Get-Job | Stop-Job | Remove-Job #If we have flagged not to run tests we can skip. this will sometimes stop the PSEXEC error 6 problem from happening on reruns IF (-NOT $SkipTests){ write-host "Starting jobs to test connectivity to servers" $Time.ConnectionTestJobStart = (Get-Date) $Params = @{ Computers = $Computers; JobLimit = $JobLimit; } #Add additional params from the script If ($SkipCoreStatus){ $Params.Add("SkipCoreStatus", $true) } If ($ContinueOnPingError){ $Params.Add("ContinueOnPingError", $true) } If ($IntensiveUser){ $Params.Add("IntensiveUser", $IntensiveUser) $Params.Add("IntensivePass", $IntensivePass) } If ($DomainUser){ $Params.Add("DomainUser", $DomainUser) $Params.Add("DomainPass", $DomainPass) } #Start connection test jobs $Computers = Run-WHAMConnectionTests @Params #Update our computer object and rerun the failed connections $Params = @{ Computers = $Computers; JobLimit = $JobLimit; } If ($SkipCoreStatus){ $Params.Add("SkipCoreStatus", $true) } If ($ContinueOnPingError){ $Params.Add("ContinueOnPingError", $true) } #Run our connection tests again on failed devices $allcomputers = Run-WHAMConnectionTestFailures @Params #Update the computers object $Computers = $allcomputers $Time.ConnectionTestJobFinish = (Get-Date) } #Get the time after tests have run $Time.ScriptJobStart = (Get-Date) write-host "Starting script execution jobs on servers" #Start the script jobs $ComputersRecieved = Run-WHAMScript -computers $Computers -joblimit $joblimit -intensiveuser $intensiveuser -intensivepass $Intensivepass -ScriptTimeout $ScriptTimeout -DownloadFile $DownloadFile #RErun the failed script jobs $ComputersRecievedfromFailures = Run-WHAMScriptFailures -Computers $ComputersRecieved -joblimit $joblimit -intensiveuser $intensiveuser -intensivepass $Intensivepass -ScriptTimeout $ScriptTimeout -DownloadFile $DownloadFile $Computers = $ComputersRecievedfromFailures $Time.ScriptJobFinish = (Get-Date) #get the end script time $Time.ScriptFinish = (Get-Date) write-host " " #Write out the script times Get-ScriptTimes -time $Time #write to the WHAM usage log and appstats iF ($FunctionSingleString.Length -EQ 0){ $FunctionSingleString = "Scriptblock" } if(-NOT $NoLogging){ $Params = @{ Computers = $Computers; version = $version functionnames = $FunctionSingleString TotalConnectionJobTime = $time.TotalConnectionTestJob TotalScriptJobTime = $time.TotalScriptJob } Update-WHAMExecutionLog @Params } If (-NOT $ReturnDataObject){ write-host " " $Params = @{ computers = $computers FunctionSingleString = $FunctionSingleString } #If user entered ticket number when we got CORE devices, add it here so we can automatically update it If ($TicketNum){ $Params.Add("TicketNum", $TicketNum) } #If user selected group when choosing templates, add it here so we can automatically add a sort order IF ($WHAMTemplates.SortOrder){ $Params.Add("SortOrder", $WHAMTemplates.SortOrder) } IF ($Collection){ $Params.Add("Collection", $true) } Get-WHAMUserOutput @Params } If ($ReturnDataObject) { return $Computers } write-host "Script end" if($Global:ContinuousMode){ cls write-host "Running WHAM in continuous mode..." -ForegroundColor Yellow & $ENV:tmp\WHAM_Controller.ps1 -ShowMenu -RunLocal }