Scripts/ExternalSources/Racktables.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
<# .SYNOPSIS Pull Racktables data, add to Neo4j .DESCRIPTION Pull Racktables data, add to Neo4j This is invoked by Connect-TheDots .PARAMETER Prefix Prefix to append to properties when we add them to Neo4j This helps identify properties that might come from mutiple sources, or where the source is ambiguous For example, row becomes RACKrow Defaults to RACK. .PARAMETER MergeProperty We use this to correlate Server data from multiple sources We assume server data should correlate if the value for this on a Racktables system matches the ServerUnique value in Neo4j Default: NameLower. Change at your own risk .PARAMETER Label What label do we assign the data we pull? Defaults to Server. Change at your own risk .PARAMETER Properties Properties to extract and select from Racktables .PARAMETER Excludes Properties to exclude (in line with transforms) .PARAMETER Transforms Properties to select again (in line with excludes) Example: *, # Keep all properties from -Properties @{ label='NameLower' expression={ @($_.System -split " ")[0].ToLower() } } This is the default. It keeps all properties from -Properties, and add a calculated NameLower .PARAMETER BaseUri Racktables "API" Base URI See http://sjoeboo.github.io/blog/2012/05/31/getting-racktables-location-info-into-puppet/ for details .PARAMETER Domains Append these to make Racktables MergeProperty value fully qualified. E.g. if Racktables NameLower is dc01, and Domains is contoso.com and contoso2.com, we merge data into servers with hostname dc01.contoso.com and/or dc01.contoso2.com .FUNCTIONALITY Dots #> [cmdletbinding()] param( [string]$Prefix = 'RACK', [string]$MergeProperty = 'NameLower', [string]$Label = 'Server', [string[]]$Properties = @( 'System' 'asset', 'row', 'rack', 'height', 'ru' ), [string[]]$Excludes, [object[]]$Transforms = @( '*', @{ label='NameLower' expression={ @($_.System -split " ")[0].ToLower() } } ), [string]$BaseUri, [string[]]$Domains, [switch]$AllLower = $Script:AllLower ) # Dot source so module import is available in this scope if($script:TestMode) { Write-Verbose "Using mock functions from $ModuleRoot/Mock/Mocks.ps1" . "$ModuleRoot/Mock/Mocks.ps1" } else { function Get-RackFacts { <# .SYNOPSIS Query RackTables data .DESCRIPTION Query RackTables data generated via duct tapi: http://sjoeboo.github.io/blog/2012/05/31/getting-racktables-location-info-into-puppet/ .EXAMPLE Get-RackFacts -ComputerName cepr* # Get all the things that start with cepr .EXAMPLE Get-RackFacts -ComputerName * # Get all the things #> param ( [string]$BaseUri, [string[]]$ComputerName ) function ConvertFrom-RackFacts { [cmdletbinding()] param( [string]$BaseUri, [string]$Name ) $Raw = $null $Rows = $null $Raw = Invoke-RestMethod -Uri "$BaseUri\$name" -ErrorAction Stop if($Raw -is [system.string]) { $Rows = $Raw -split "`n" } if($Rows -and $Rows.count -gt 1) { $Output = @{System = [System.Web.HttpUtility]::UrlDecode($Name)} foreach($Row in $Rows) { if($Row -match ":") { $SplitRow = @($Row -split ":") $Key = $SplitRow[0] $Count = $SplitRow.count $Value = $SplitRow[1..$Count] -join ":" if($Value -is [system.string]){$Value = $Value.trim()} if($key -is [system.string]){$key = $key.trim()} $Output.add($Key, $Value) } } [pscustomobject]$Output } } foreach($Name in $ComputerName) { # this isn't a real API, it's duct tape from a blog post - handy, but... we'll do the work. $SearchAll = $False $Wildcard = $False if($Name -match '\*') { $SearchAll = $True $WildCard = $True } try { ConvertFrom-RackFacts -BaseUri $BaseUri -Name $Name -ErrorAction Stop } catch { if($_.Exception.Message -match '404') { $SearchAll = $True } else { Write-Error $_ } } if($SearchAll) { if(-not $Wildcard) { $Name = "*$Name*" } $d = Invoke-WebRequest $BaseUri $MatchingLinks = $d.links.where({$_.href -notmatch "^\?|^/rack" -and $_.href -like $Name}) foreach($Link in $MatchingLinks) { ConvertFrom-RackFacts -BaseUri $BaseUri -Name $Link.href } } } } } $Unique = "${Prefix}${MergeProperty}" $Date = Get-Date $Nodes = Get-RackFacts -BaseUri $BaseUri -ComputerName * $Nodes = $Nodes | Select-Object -Property $Properties | Select-Object -Property $Transforms $names = $nodes.NameLower $NameHash = @{} $Dupes = foreach($Name in $Names) { if(-not $NameHash.ContainsKey($Name)){ $NameHash.Add($Name,$null) } else { $Name } } $Nodes = Foreach($Node in $Nodes.where({$Dupes -notcontains $_.NameLower})) { $Output = Add-PropertyPrefix -Prefix $Prefix -Object $Node Add-Member -InputObject $Output -MemberType NoteProperty -Name "${script:CMDBPrefix}${Prefix}UpdateDate" -Value $Date -Force if($AllLower) { ConvertTo-Lower -InputObject $Output } $Output } $TotalCount = $Nodes.count $Count = 0 Foreach($Node in $Nodes) { Write-Progress -Activity "Updating Neo4j" -Status "Adding $($Node.$Unique)" -PercentComplete (($Count / $TotalCount)*100) $Count++ foreach($Domain in $Domains) { # Update existing, do not create new nodes, data is garbage Set-Neo4jNode -Label $Label -Hash @{$script:ServerUnique = "$($Node.$Unique).$Domain"} -InputObject $Node -NoCreate } } |