VaultControl.psm1
|
function Add-ObjectDetail { <# .SYNOPSIS Decorate an object with - A TypeName - New properties - Default parameters .DESCRIPTION Helper function to decorate an object with - A TypeName - New properties - Default parameters .PARAMETER InputObject Object to decorate. Accepts pipeline input. .PARAMETER TypeName Typename to insert. This will show up when you use Get-Member against the resulting object. .PARAMETER PropertyToAdd Add these noteproperties. Format is a hashtable with Key (Property Name) = Value (Property Value). Example to add a One and Date property: -PropertyToAdd @{ One = 1 Date = (Get-Date) } .PARAMETER DefaultProperties Change the default properties that show up .PARAMETER Passthru Whether to pass the resulting object on. Defaults to true .EXAMPLE # # Create an object to work with $Object = [PSCustomObject]@{ First = 'Cookie' Last = 'Monster' Account = 'CMonster' } #Add a type name and a random property Add-ObjectDetail -InputObject $Object -TypeName 'ApplicationX.Account' -PropertyToAdd @{ AnotherProperty = 5 } # First Last Account AnotherProperty # ----- ---- ------- --------------- # Cookie Monster CMonster 5 #Verify that get-member shows us the right type $Object | Get-Member # TypeName: ApplicationX.Account ... .EXAMPLE # # Create an object to work with $Object = [PSCustomObject]@{ First = 'Cookie' Last = 'Monster' Account = 'CMonster' } #Add a random property, set a default property set so we only see two props by default Add-ObjectDetail -InputObject $Object -PropertyToAdd @{ AnotherProperty = 5 } -DefaultProperties Account, AnotherProperty # Account AnotherProperty # ------- --------------- # CMonster 5 #Verify that the other properties are around $Object | Select -Property * # First Last Account AnotherProperty # ----- ---- ------- --------------- # Cookie Monster CMonster 5 .NOTES This breaks the 'do one thing' rule from certain perspectives... The goal is to decorate an object all in one shot This abstraction simplifies decorating an object, with a slight trade-off in performance. For example: 10,000 objects, add a property and typename: Add-ObjectDetail: ~4.6 seconds Add-Member + PSObject.TypeNames.Insert: ~3 seconds Initial code borrowed from Shay Levy: http://blogs.microsoft.co.il/scriptfanatic/2012/04/13/custom-objects-default-display-in-powershell-30/ .LINK http://ramblingcookiemonster.github.io/Decorating-Objects/ .FUNCTIONALITY PowerShell Language #> [CmdletBinding()] param( [Parameter( Mandatory = $true, Position = 0, ValueFromPipeline = $true )] [ValidateNotNullOrEmpty()] [psobject[]]$InputObject, [Parameter( Mandatory = $false, Position = 1)] [string]$TypeName, [Parameter( Mandatory = $false, Position = 2)] [System.Collections.Hashtable]$PropertyToAdd, [Parameter( Mandatory = $false, Position = 3)] [ValidateNotNullOrEmpty()] [Alias('dp')] [System.String[]]$DefaultProperties, [boolean]$Passthru = $True ) Begin { if($PSBoundParameters.ContainsKey('DefaultProperties')) { # define a subset of properties $ddps = New-Object System.Management.Automation.PSPropertySet DefaultDisplayPropertySet, $DefaultProperties $PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]$ddps } } Process { foreach($Object in $InputObject) { switch ($PSBoundParameters.Keys) { 'PropertyToAdd' { foreach($Key in $PropertyToAdd.Keys) { #Add some noteproperties. Slightly faster than Add-Member. $Object.PSObject.Properties.Add( ( New-Object System.Management.Automation.PSNoteProperty($Key, $PropertyToAdd[$Key]) ) ) } } 'TypeName' { #Add specified type [void]$Object.PSObject.TypeNames.Insert(0, $TypeName) } 'DefaultProperties' { # Attach default display property set Add-Member -InputObject $Object -MemberType MemberSet -Name PSStandardMembers -Value $PSStandardMembers } } if($Passthru) { $Object } } } } Function ConvertTo-InsecureString { <# .SYNOPSIS Returns string value from SecureString input .DESCRIPTION Gets the decoded string value of an encoded SecureString .PARAMETER SecureString The SecureString to decode .EXAMPLE ConvertTo-InsecureString $SecureStringValue #> [CmdLetBinding()] [OutputType('System.String')] Param ( [Parameter( Mandatory = $True)] [System.Security.SecureString]$SecureString ) Try { $ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($SecureString) [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ptr) } Finally { [System.Runtime.InteropServices.Marshal]::ZeroFreeGlobalAllocUnicode($ptr) } } Function Invoke-PARClient { <# .SYNOPSIS Defines specified PARClient command and arguments .DESCRIPTION Defines a PARClient process object with arguments required for specific command. .PARAMETER PARClient The Path to PARClient.exe. Defaults to value of $Script:PAR.ClientPath, which is set during module import or via Set-PARConfiguration. .PARAMETER Server The name or address of the Vault server to target .PARAMETER Password SecureString of password used for PARClient operations .PARAMETER Credential A credential object containing the password used for PARClient operations .PARAMETER PassFile The path to a "password" file created by PARClient.exe, containing the encrypted password value used for remote operations via PARClient .PARAMETER CommandParameters The PARClient command to execute .PARAMETER PAROptions Additional command parameters. By default specifies /Q /C. A new /StateFileName file in the local temp directory is specified for each command, and deleted after the command completes, so log queries are not limited to records unread by a previous command. .PARAMETER RemainingArgs A catch all parameter, accepts any remaining values from pipeline. Intended to suppress errors when piping in an object. .EXAMPLE Invoke-PARClient -Server EPV1 -Password $SecureString -CommandParameters "GetParm Vault DebugLevel" Invokes the GetParm action against the Vault on EPV1 and returns the DebugLevel parameter value. .NOTES AUTHOR: Pete Maan #> [CmdLetBinding(SupportsShouldProcess)] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "RemainingArgs", Justification = "Catch-all for unbound pipeline properties")] param( [Parameter( Mandatory = $False, ValueFromPipelineByPropertyName = $True )] [string]$PARClient = $Script:PAR.ClientPath, [Parameter( Mandatory = $False, ValueFromPipelineByPropertyName = $True )] [int]$Port = $Script:PAR.Port, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True )] [string]$Server, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True, ParameterSetName = "Password" )] [securestring]$Password, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True, ParameterSetName = "Credential" )] [pscredential]$Credential, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True, ParameterSetName = "PassFile" )] [ValidateScript( {Test-Path $_})] [string]$PassFile, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True )] [string]$CommandParameters, [Parameter(Mandatory = $False, ValueFromPipelineByPropertyName = $True )] [string]$PAROptions = "/Q /C", [Parameter(Mandatory = $False, ValueFromPipelineByPropertyName = $False, ValueFromRemainingArguments = $true )] $RemainingArgs ) Begin { Try { $null = Get-Variable -Name PAR -ErrorAction Stop if($PAR.PSObject.Properties.Name -notcontains "ClientPath") { Write-Error "Heads Up!" -ErrorAction Stop } } Catch {throw "PARClient.exe not found `nRun Set-PARConfiguration to set path to PARClient"} #Create process $Process = New-Object System.Diagnostics.Process } Process { Switch($PSCmdlet.ParameterSetName) { "Credential" { $ClearTextPassword = $($Credential.GetNetworkCredential().Password) $PARCommand = "$Server/$ClearTextPassword"; break } "Password" { $ClearTextPassword = ConvertTo-InsecureString -SecureString $Password $PARCommand = "$Server/$ClearTextPassword"; break } "PassFile" {$PARCommand = "$Server /UsePassFile `"$PassFile`""; break} } If($Port -gt 0) { $PARCommand = "$PARCommand /Port $Port" } $CommandParameters = $CommandParameters -replace ('^', '"') $CommandParameters = $CommandParameters -replace ('$', '"') if ($PSCmdlet.ShouldProcess($Server, "$CommandParameters")) { $StateFile = Join-Path $env:temp "$([guid]::NewGuid()).tmp" $Arguments = "$PARCommand /StateFileName `"$StateFile`" $PAROptions $CommandParameters" Write-Debug "Command Arguments: $Arguments" #Assign process parameters $Process.StartInfo.WorkingDirectory = "$(Split-Path $PARClient -Parent)" $Process.StartInfo.Filename = $PARClient $Process.StartInfo.Arguments = $Arguments $Process.StartInfo.RedirectStandardOutput = $True $Process.StartInfo.RedirectStandardError = $True $Process.StartInfo.UseShellExecute = $False $Process.StartInfo.CreateNoWindow = $True $Process.StartInfo.WindowStyle = "hidden" #Start Process Try { $Result = Start-PARClientProcess -Process $Process } Finally { Remove-Item -Path $StateFile -Force -ErrorAction SilentlyContinue } $Result | Add-Member -MemberType NoteProperty -Name Server -Value $Server if($Result.StdOut -match '((?:^[A-Z]{3,5}[0-9]{3}[A-Z])|(?:ERROR \(\d+\)))(?::)? ([^\r\n]+)') { #PARCL002S Authentication failure. Write-Error -Message $Matches[2] -ErrorId $Matches[1] } ElseIf($Result.StdOut -match '(.+) \((Reason: \d+)\)') { #Cannot get parameter DisableExceptionHandling. (Reason: 7) Write-Error -Message $Matches[1] -ErrorId $Matches[2] } Else {$Result} } } End { $Process.Dispose() } } Function Start-PARClientProcess { <# .SYNOPSIS Starts PARClient process .DESCRIPTION Designed to receive PARClient process object from Invoke-PARClient. Returns Object containing ExitCode, StdOut & StdErr .PARAMETER Process System.Diagnostics.Process object containing PARClient parameters .EXAMPLE Start-PARClientProcess -Process $Process Invokes the Start method on the $Process object .NOTES AUTHOR: Pete Maan #> [CmdLetBinding(SupportsShouldProcess)] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification = "ShouldProcess handling is in Invoke-PARClient")] param( [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True )] [System.Diagnostics.Process]$Process ) Begin { } Process { #Start Process $Process.start() | Out-Null #Read Output Stream First $StdOut = $Process.StandardOutput.ReadToEnd() $StdErr = $Process.StandardError.ReadToEnd() #If you wait for the process to exit before reading StandardOutput #the process can block trying to write to it, so the process never ends. $Process.WaitForExit() [PSCustomObject] @{ "ExitCode" = $Process.ExitCode "StdOut" = $StdOut "StdErr" = $StdErr } } End { $Process.Dispose() } } # .ExternalHelp VaultControl-help.xml Function Get-PARComponent { [CmdletBinding()] Param( [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [string]$Server, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Password" )] [securestring]$Password, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Credential" )] [pscredential]$Credential, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True, ParameterSetName = "PassFile" )] [ValidateScript( {Test-Path $_ -PathType Leaf})] [string]$PassFile, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [ValidateSet("Vault", "PADR", "ENE", "CVM")] [string]$Component ) Process { $PSBoundParameters.Add("CommandParameters", "Status $Component") $Result = Invoke-PARClient @PSBoundParameters If($Result.StdOut) { switch -regex ($Result.StdOut) { 'running' {$Status = "Running"; break} 'starting' {$Status = "Starting"; break} 'stopped' {$Status = "Stopped"; break} default {$Status = $Result.StdOut; break} } [PSCustomObject]@{ "Server" = $Result.Server "Component" = $Component "Status" = $Status } } } } # .ExternalHelp VaultControl-help.xml Function Get-PARComponentConfig { [CmdletBinding()] Param( [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [string]$Server, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Password" )] [securestring]$Password, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Credential" )] [pscredential]$Credential, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True, ParameterSetName = "PassFile" )] [string]$PassFile, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [ValidateSet("Vault", "PADR")] [string]$Component, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [ValidateSet("DefaultTimeout", "MTU", "SecurityNotification", "DebugLevel", "DisableExceptionHandling", "EnableCheck", "EnableReplicate", "EnableFailover", "EnableDBSync", "FailoverMode")] [string]$Parameter ) Begin { $VaultSet = "DefaultTimeout", "MTU", "SecurityNotification", "DebugLevel", "DisableExceptionHandling" $PADRSet = "EnableCheck", "EnableReplicate", "EnableFailover", "EnableDBSync", "FailoverMode" } Process { Switch($Component) { "Vault" { If($VaultSet -notcontains $Parameter) {throw "Not a valid DBPARM.ini Parameter"} } "PADR" { If($PADRSet -notcontains $Parameter) {throw "Not a valid PADR.ini Parameter"} } } $PSBoundParameters.Add("CommandParameters", "GetParm $Component $($PSBoundParameters["Parameter"])") $Result = Invoke-PARClient @PSBoundParameters If($Result.StdOut) { If($Result.StdOut -match "=") { $Value = ($Result.StdOut).Split("=")[1] } Else {$Value = $Result.StdOut} [PSCustomObject]@{ "Server" = $Result.Server "Component" = $Component "Parameter" = $($PSBoundParameters["Parameter"]) "Value" = $Value.Trim() } } } } # .ExternalHelp VaultControl-help.xml Function Get-PARComponentLog { [CmdletBinding()] Param( [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [string]$Server, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Password" )] [securestring]$Password, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Credential" )] [pscredential]$Credential, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True, ParameterSetName = "PassFile" )] [ValidateScript( {Test-Path $_ -PathType Leaf})] [string]$PassFile, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [ValidateSet("Vault", "PADR", "ENE", "CVM")] [string]$Component, [Parameter( Mandatory = $false, ValueFromPipelineByPropertyName = $true )] [ValidateSet("Console", "Trace")] [string]$LogFile = "Console", [Parameter( Mandatory = $false, ValueFromPipelineByPropertyName = $true )] [datetime]$TimeFrom, [Parameter( Mandatory = $false, ValueFromPipelineByPropertyName = $true )] [int]$Lines ) Begin { $PADR = '^\[(\d+\/\d+\/\d+\s+\d+\:\d+\:\d+\.\d+)\]\W+([A-Z]+\d+[A-Z](?:\s))?(.+)$' $Vault = '^(\d+\/\d+\/\d+ \d+:\d+:\d+) ([A-Z]+[0-9]+[A-Z]) (.+)$' $ENEConsole = '^\[(\d+\/\d+\/\d+\s\W\s\d+\:\d+\:\d+)\]\W+([A-Z]+\d+[A-Z])\s(.+)$' $ENETrace = '^\[(\d+\/\d+\/\d+(?:\s\W)\s\d+\:\d+\:\d+)\.\d+\].+\|\s([A-Z]+(?:[A-Z]|\d)[A-Z]\d+[A-Z](?:\s))?(.+)$' } Process { $Command = "GetLog $Component" if(($Component -eq "VAULT") -or ($Component -eq "PADR")) { if($PSBoundParameters.ContainsKey("TimeFrom")) { $DateStamp = (Get-Date $($PSBoundParameters["TimeFrom"]) -Format ddMMyyyy:HHmm) $Command = "$Command /TimeFrom $DateStamp" } } if($Component -eq "VAULT") { if($PSBoundParameters.ContainsKey("Lines")) { $Command = "$Command /Lines $($PSBoundParameters["Lines"])" } } if(($Component -eq "ENE") -or ($Component -eq "CVM")) { $Command = "$Command /LogFile $($PSBoundParameters["LogFile"])" } $PSBoundParameters.Add("CommandParameters", "$Command") switch ($Component) { "PADR" {$Pattern = $PADR; break} "Vault" {$Pattern = $Vault; break} "ENE" { if ($($PSBoundParameters["LogFile"]) -eq "Console") { $Pattern = $ENEConsole; break } elseif ($($PSBoundParameters["LogFile"]) -eq "Trace") { $Pattern = $ENETrace; break } } default {$Pattern = '(.+)'; break} } $Result = Invoke-PARClient @PSBoundParameters If($Result.StdOut) { ($Result.StdOut).Split("`n") | ForEach-Object { $LogEntry = ($_ | Select-String $Pattern -AllMatches) if($LogEntry -match '\S') { [PSCustomObject]@{ "Time" = $LogEntry.Matches.Groups[1].Value -replace '(\s\W\s)', ' ' "Code" = $LogEntry.Matches.Groups[2].Value "Message" = $LogEntry.Matches.Groups[3].Value } | Add-ObjectDetail -typename VaultControl.Log.Component } } } } } # .ExternalHelp VaultControl-help.xml Function Get-PARServer { [CmdletBinding()] Param( [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [string]$Server, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Password" )] [securestring]$Password, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Credential" )] [pscredential]$Credential, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True, ParameterSetName = "PassFile" )] [string]$PassFile ) Process { Try { $ErrorActionPreference = "Stop" $PSBoundParameters["CommandParameters"] = "GetCPU" $CPU = Invoke-PARClient @PSBoundParameters $PSBoundParameters["CommandParameters"] = "GetDiskUsage" $Disk = Invoke-PARClient @PSBoundParameters $PSBoundParameters["CommandParameters"] = "GetMemoryUsage" $Memory = Invoke-PARClient @PSBoundParameters $PSBoundParameters["CommandParameters"] = "List" $Components = Invoke-PARClient @PSBoundParameters #Remove PARAgent version header line $CPU, $Disk, $Memory, $Components = $CPU, $Disk, $Memory, $Components | ForEach-Object { $_.StdOut -replace '(?m)^PARAgent version:.*(\r?\n)?', '' } If($CPU) { $CPU = ($CPU | Select-String '(\d+\.\d+)' -AllMatches).Matches.Value } Else {$CPU = $null} If($Disk) { $Disk = $Disk | Select-String '(.+)' -AllMatches | ForEach-Object { $DiskInfo = $_.Line.Split(" ") For ($i = 0 ; $i -lt $DiskInfo.count ; $i += 3) { $Drive = $DiskInfo[$i..($i + 3)] [PSCustomObject]@{ "Drive" = $Drive[0] "FreeSpace(MB)" = ($Drive[1] | Select-String '(\d+)' -AllMatches).Matches.Value "FreeSpace(%)" = ($Drive[2] | Select-String '(\d+\.\d+)' -AllMatches).Matches.Value } } } } Else {$Disk = $null} If($Memory) { $Memory = ($Memory | Select-String '(.+)' -AllMatches).Matches.Value | ForEach-Object { $MemoryInfo = $_.Split(":") $MemoryData = ($MemoryInfo[1] | Select-String '(\S+)' -AllMatches).Matches.Value [PSCustomObject]@{ "MemoryType" = ($MemoryInfo[0].Split(" "))[0] "Total(K)" = (($MemoryData[0]).Split("=")[1] | Select-String '(\d+)' -AllMatches).Matches.Value "Free(K)" = (($MemoryData[1]).Split("=")[1] | Select-String '(\d+)' -AllMatches).Matches.Value "Used(%)" = (($MemoryData[2]).Split("=")[1] | Select-String '(\d+\.\d+)' -AllMatches).Matches.Value } } } Else {$Memory = $null} If($Components) { $Components = ($Components | Select-String '(.+)' -AllMatches).Matches.Value | ForEach-Object { $Component = $_.Split(" ") $Version = ($_ | Select-String "(\d+\D\d+\D\d+\D\d+)" -AllMatches).Matches.Value [PSCustomObject]@{ Component = $Component[0] Version = $Version } } } Else {$Components = $null} [PSCustomObject]@{ "Server" = $Server.ToUpper() "CPU(%)" = $CPU "Disk" = $Disk "Memory" = $Memory "Components" = $Components } } Catch {throw $_} } } # .ExternalHelp VaultControl-help.xml Function Get-PARServerLog { [CmdletBinding()] Param( [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [string]$Server, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Password" )] [securestring]$Password, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Credential" )] [pscredential]$Credential, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True, ParameterSetName = "PassFile" )] [ValidateScript( {Test-Path $_ -PathType Leaf})] [string]$PassFile, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [ValidateSet("Application", "Security", "System")] [string]$LogName, [Parameter( Mandatory = $false, ValueFromPipelineByPropertyName = $true )] [datetime]$TimeFrom = (Get-Date).AddDays(-1) ) Begin { $Pattern = 'EventLogRecordTime:(.+\s)Source:(.+\s)Computer:(.+\s)Event ID:(.+\s)Event Type:(.+\s)Description:(.+(?:[\S\s]+?))(?=\Z|EventLogRecordTime)' } Process { $Command = "GetOSLog /Name $LogName /TimeFrom $(Get-Date $TimeFrom -Format ddMMyyyy:HHmm)" $PSBoundParameters.Add("CommandParameters", "$Command") $Result = Invoke-PARClient @PSBoundParameters If($Result.StdOut) { $Logs = $Result.StdOut -replace '(?m)^PARAgent version:.*(\r?\n)?', '' | Select-String $Pattern -AllMatches $Logs | Select-Object -ExpandProperty Matches | ForEach-Object { [PSCustomObject]@{ "EventLogRecordTime" = ($_.Groups[1].Value).Trim() "Source" = ($_.Groups[2].Value).Trim() "Computer" = ($_.Groups[3].Value).Trim() "EventID" = [int]([int64](($_.Groups[4].Value).Trim()) -band 0xFFFF) "EventType" = ($_.Groups[5].Value).Trim() "Description" = ($_.Groups[6].Value).Trim() } | Add-ObjectDetail -typename VaultControl.Log.Server } } } } # .ExternalHelp VaultControl-help.xml Function Get-PARService { [CmdletBinding()] Param( [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [string]$Server, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Password" )] [securestring]$Password, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Credential" )] [pscredential]$Credential, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True, ParameterSetName = "PassFile" )] [ValidateScript( {Test-Path $_ -PathType Leaf})] [string]$PassFile, [Parameter( Mandatory = $false, ValueFromPipelineByPropertyName = $true )] [string]$ServiceName = "*" ) Process { $ServiceName = $ServiceName -replace '(.+)', '\"$&\"' $PSBoundParameters.Add("CommandParameters", "ServiceStatus /ServiceName $ServiceName") $Result = Invoke-PARClient @PSBoundParameters If($Result.StdOut) { ($Result.StdOut).Split("`n") | ForEach-Object { $Service = ($_ | Select-String '^(.+)is\s([a-z]+)' -AllMatches) If($Service -match '\S') { [PSCustomObject]@{ "Server" = $Result.Server "Service" = $Service.Matches.Groups[1].Value "Status" = $($Service.Matches.Groups[2].Value).Substring(0, 1).ToUpper() + $($Service.Matches.Groups[2].Value).Substring(1) } } } } } } # .ExternalHelp VaultControl-help.xml Function New-PARPassFile { [CmdletBinding(SupportsShouldProcess)] Param( [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [ValidateNotNullOrEmpty()] [string]$Path ) Begin { If(-not $Script:PAR.ClientPath) { throw "PARClient.exe not found `nRun Set-PARConfiguration to set path to PARClient" } } Process { $FilePath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) $Folder = Split-Path -Path $FilePath -Parent If($PSCmdlet.ShouldProcess($FilePath, "Create PARClient Password File")) { If(-not (Test-Path -Path $Folder -PathType Container)) { $null = New-Item -Path $Folder -ItemType Directory -Force } $Process = Start-Process -FilePath $Script:PAR.ClientPath -ArgumentList "/CreatePassFile `"$FilePath`"" ` -WorkingDirectory (Split-Path -Path $Script:PAR.ClientPath -Parent) -NoNewWindow -Wait -PassThru If(($Process.ExitCode -eq 0) -and (Test-Path -Path $FilePath -PathType Leaf)) { Get-Item -Path $FilePath } Else { Write-Error -Message "Failed to create password file $FilePath (Exit Code: $($Process.ExitCode))" -ErrorId "PassFileNotCreated" } } } } # .ExternalHelp VaultControl-help.xml Function Restart-PARComponent { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification = "ShouldProcess handling is in Invoke-PARClient")] Param( [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [string]$Server, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Password" )] [securestring]$Password, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Credential" )] [pscredential]$Credential, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True, ParameterSetName = "PassFile" )] [ValidateScript( {Test-Path $_ -PathType Leaf})] [string]$PassFile, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [ValidateSet("Vault", "PADR")] [string]$Component ) Process { $PSBoundParameters.Add("CommandParameters", "Restart $Component") $Result = Invoke-PARClient @PSBoundParameters If($Result.StdOut) { $Service = ($Result.StdOut | Select-String '(restarted|Error)' -AllMatches) [PSCustomObject]@{ "Server" = $Result.Server "Component" = $Component "Status" = $($Service.Matches.Groups[1].Value).Substring(0, 1).ToUpper() + $($Service.Matches.Groups[1].Value).Substring(1) } } } } # .ExternalHelp VaultControl-help.xml Function Restart-PARServer { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification = "ShouldProcess handling is in Invoke-PARClient")] Param( [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [string]$Server, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Password" )] [securestring]$Password, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Credential" )] [pscredential]$Credential, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True, ParameterSetName = "PassFile" )] [ValidateScript( {Test-Path $_ -PathType Leaf})] [string]$PassFile ) Process { $PSBoundParameters.Add("CommandParameters", "REBOOT") $Result = Invoke-PARClient @PSBoundParameters If($Result.StdOut) { [PSCustomObject]@{ "Server" = $Result.Server "Status" = $Result.StdOut } } } } # .ExternalHelp VaultControl-help.xml Function Set-PARComponentConfig { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Low')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification = "ShouldProcess handling is in Invoke-PARClient")] Param( [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [string]$Server, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Password" )] [securestring]$Password, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Credential" )] [pscredential]$Credential, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [ValidateSet("Vault", "PADR")] [string]$Component, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True, ParameterSetName = "PassFile" )] [string]$PassFile, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [ValidateSet("DefaultTimeout", "MTU", "SecurityNotification", "DebugLevel", "DisableExceptionHandling", "EnableCheck", "EnableReplicate", "EnableFailover", "EnableDBSync", "FailoverMode")] [string]$Parameter, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [string]$Value, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [ValidateSet("Temporary", "Permanent", "Immediate")] [string]$Mode ) Process { $PSBoundParameters.Add("CommandParameters", "SetParm $Component $Parameter=$Value /$Mode") $Result = Invoke-PARClient @PSBoundParameters If($Result.StdOut) { $Update = ($Result.StdOut | Select-String '(success|Error)' -AllMatches) [PSCustomObject]@{ "Server" = $Result.Server "Component" = $Component "Parameter" = $($PSBoundParameters["Parameter"]) "Value" = $Value "Mode" = $($PSBoundParameters["Mode"]) "Status" = $($Update.Matches.Groups[1].Value).Substring(0, 1).ToUpper() + $($Update.Matches.Groups[1].Value).Substring(1) "Message" = $Result.StdOut } } } } # .ExternalHelp VaultControl-help.xml Function Set-PARConfiguration { [CmdletBinding(SupportsShouldProcess)] Param( [Parameter( Mandatory = $false, ValueFromPipelineByPropertyName = $true )] [ValidateScript( {Test-Path $_ -PathType Leaf})] [ValidateNotNullOrEmpty()] [string]$ClientPath, [Parameter( Mandatory = $false, ValueFromPipelineByPropertyName = $true )] [ValidateNotNullOrEmpty()] [int]$Port ) Begin { $Defaults = [pscustomobject]@{} } Process { If($PSBoundParameters.Keys -contains "ClientPath") { $Defaults | Add-Member -MemberType NoteProperty -Name ClientPath -Value $ClientPath } If($PSBoundParameters.Keys -contains "Port") { $Defaults | Add-Member -MemberType NoteProperty -Name Port -Value $Port } } End { Set-Variable -Name PAR -Value $Defaults -Scope Script $Script:PAR | Select-Object -Property * | Export-Clixml -Path "$env:HOMEDRIVE$env:HomePath\PARConfiguration.xml" -Force } } # .ExternalHelp VaultControl-help.xml Function Start-PARComponent { [CmdletBinding(SupportsShouldProcess)] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification = "ShouldProcess handling is in Invoke-PARClient")] Param( [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [string]$Server, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Password" )] [securestring]$Password, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Credential" )] [pscredential]$Credential, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True, ParameterSetName = "PassFile" )] [string]$PassFile, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [ValidateSet("Vault", "PADR", "ENE", "CVM")] [string]$Component, [Parameter( Mandatory = $false, ValueFromPipelineByPropertyName = $false )] [switch]$Last ) Process { $Command = "Start $Component" if($Component -eq "Vault") { if($PSBoundParameters.ContainsKey("Last")) { $Command = "$Command /Last" } } $PSBoundParameters.Add("CommandParameters", "$Command") $Result = Invoke-PARClient @PSBoundParameters If($Result.StdOut) { $Service = ($Result.StdOut | Select-String '(started|Error)' -AllMatches) [PSCustomObject]@{ "Server" = $Result.Server "Component" = $Component "Status" = $($Service.Matches.Groups[1].Value).Substring(0, 1).ToUpper() + $($Service.Matches.Groups[1].Value).Substring(1) } } } } # .ExternalHelp VaultControl-help.xml Function Stop-PARComponent { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification = "ShouldProcess handling is in Invoke-PARClient")] Param( [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [string]$Server, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Password" )] [securestring]$Password, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Credential" )] [pscredential]$Credential, [Parameter( Mandatory = $True, ValueFromPipelineByPropertyName = $True, ParameterSetName = "PassFile" )] [string]$PassFile, [Parameter( Mandatory = $true, ValueFromPipelineByPropertyName = $true )] [ValidateSet("Vault", "PADR", "ENE", "CVM")] [string]$Component, [Parameter( Mandatory = $false, ValueFromPipelineByPropertyName = $true )] [ValidateSet("Normal", "Immediate", "Terminate")] [string]$ShutdownMode ) Process { $Command = "Stop $Component" If($Component -eq "Vault") { if($PSBoundParameters.ContainsKey("ShutdownMode")) { $Command = "$Command /$($PSBoundParameters["ShutdownMode"])" } } $PSBoundParameters.Add("CommandParameters", "$Command") $Result = Invoke-PARClient @PSBoundParameters If($Result.StdOut) { $Service = ($Result.StdOut | Select-String '(stopped|Error)' -AllMatches) [PSCustomObject]@{ "Server" = $Result.Server "Component" = $Component "Status" = $($Service.Matches.Groups[1].Value).Substring(0, 1).ToUpper() + $($Service.Matches.Groups[1].Value).Substring(1) } } } } #Read config and make available in script scope $ConfigFile = "$env:HOMEDRIVE$env:HomePath\PARConfiguration.xml" If(Test-Path $ConfigFile) { Write-Verbose "Importing Settings: $ConfigFile" $config = Import-Clixml -Path $ConfigFile Set-Variable -Name PAR -Value $config -Scope Script } |