## Info ## ## __| __ __| | / __| ## ( | . < ( _ \ _| -_) ## \___| _| _|\_\ \___| \___/ _| \___| ## ## Author: Nielsen Pierce ## Updated by Martin Howlett and Mark Wichall ## Description: PSv3 module for Querying Core Device(s) from cmd line ## Requires Powershell v3 ## Version 2.4 - Added new version of get-coredevice(s) ## Version 2.3 - Improved Get-CoreToken and validation options around the token ## Version 2.2 - Removed backup IP after CORE update ## Version 2.1 - Removed backup IP after CORE update ## Version 2.0 ## Define Functions ## Global Authentication Cmdlets Function Get-CoreToken { Param( [Parameter()]$RSAToken ) $count = 0 While (-NOT $Response) { #The -erroraction param doesnt work on Invoke-RestMethod so we have to temporarily turn it off for the whole script $OldEAP = $ErrorActionPreference $ErrorActionPreference = 'SilentlyContinue' IF ([Environment]::GetEnvironmentVariable("CoreUser")) { $Username = [Environment]::GetEnvironmentVariable("CoreUser") } ELSE { #Prompt for user name $Username = Read-Host "Please enter your username to login to CORE" } if(-NOT $RSAToken){ $RSAToken = $([System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($(Read-Host -Prompt "Please enter your RSA token to login to CORE" -AsSecureString)))) } #Send request to CORE and ask for the password $Response = Invoke-RestMethod -Uri "https://ws.core.rackspace.com/ctkapi/login/$username/" -Body "{`"password`":`"$RSAToken`"}" -ContentType "application\json" -Method "Post" #Enable the error action again $ErrorActionPreference = $OldEAP #If we have not had a response from the invoke-restmethod then creds are probably wrong, so inform the user IF (-NOT $Response) { $count ++ If ($count -eq 3) { #After 3 tries break, else we will be here all day write-host "CORE credentials failed 3 times. Giving up!" -ForegroundColor Red break } write-host "CORE Username or password incorrect, please retype credentials" -ForegroundColor Red } } #Save our username [Environment]::SetEnvironmentVariable("CoreUser",$Username, "User") #Save our token to our variables Save-COREToken -COREToken $Response.authtoken Return $Response.authtoken } Function Save-COREToken { Param( [Parameter(Mandatory=$true)]$COREToken ) #Save the token and username to our Environment Variables [Environment]::SetEnvironmentVariable("CoreToken",$COREToken, "User") $Global:Token = $COREToken } Function Validate-CoreTokenRequest { Param( [Parameter(Mandatory=$true)]$COREToken ) #The -erroraction param doesnt work on Invoke-RestMethod so we have to temporarily turn it off for the whole script $OldEAP = $ErrorActionPreference $ErrorActionPreference = 'SilentlyContinue' $URL = "https://ws.core.rackspace.com/ctkapi/session/$COREToken" #I have seen a weird error where this command will return "The underlying connection was closed: An unexpected error occurred on a send." #As such if it comes back as blank we will try and webclient, which seems to work more reliably $tokenValid = Invoke-RestMethod -Uri $URL -Method GET IF (-NOT $tokenValid) { #try downloading via the web client $wc = New-Object System.Net.WebClient $tokenValid = ($wc.DownloadString($url)) | ConvertFrom-Json } #Enable the error action again $ErrorActionPreference = $OldEAP Return $tokenValid } Function Validate-CoreToken{ Param( [Parameter()][switch]$ReturnBooleen ) #Test the $Global:Token Variable $COREToken = $null $COREToken = $Global:token Write-Verbose "Global:Token: $COREToken" if ($Global:token -eq $null){ $Valid = $false Write-Verbose "Global:Token is null" }else{ $Valid = (Validate-CoreTokenRequest -COREToken $COREToken).valid Write-Verbose "Global:Token is $Valid after testing in CORE" } if($Valid){ Save-COREToken -COREToken $COREToken Write-Verbose "Saving existing Global:Token" if($ReturnBooleen){ return $true $NoMoreoutput = $true } }else{ #Test the Environment Variable $COREToken = $null $CoreToken = [Environment]::GetEnvironmentVariable("CoreToken") Write-Verbose "ENviroment token = $CoreToken" if ($CoreToken -eq $null){ $Valid = $false Write-Verbose "Enviroment token is null" }else{ $Valid = (Validate-CoreTokenRequest -COREToken $COREToken).valid Write-Verbose "Enviroment token is $Valid after testing in CORE" } } if(-NOT $NoMoreoutput){ if($Valid){ Save-COREToken -COREToken $COREToken Write-Verbose "Saving existing enviroment token" if($ReturnBooleen){ return $true } }else{ if($ReturnBooleen){ return $false }else{ $COREToken = Get-CoreToken Write-Verbose "Getting new token $COREToken" } } } } ## Define Core Module Functions Function Get-CoreQuery{ Param( [Parameter(Mandatory=$true)]$JSON ) #Search each line of the JSON, if load_arg is blank or NULL then cancel ForEach ($line in $JSON) { IF (($line -like "*load_arg*`"`"*") -OR ($line -like "*load_arg*`"NULL`"*")) { write-host "Blank or null value detected in line $line in CTKCore module. Cancelling script" -ForegroundColor Red exit } } #Make sure our token is valid Validate-CoreToken #Submit the CORE query Invoke-RestMethod -Uri "https://ws.core.rackspace.com/ctkapi/query" -ContentType "application\json" -Method "Post" -Headers @{"X-Auth"=$global:token} -Body $JSON -TimeoutSec 180 } ## Core CTKAPI Cmdlets # Get Functions Function Get-ComputerAttributes { Param( [Parameter ()][switch]$RackPW ) #Create array of all params we want to get from devices in CORE $ComputerAttributes = @( "account.name", "number", "name", "primary_ip", "primary_nat_ip", "is_windows", "os_name", "nickname", "status.active", "status.name", "os_type", "platform_name", "platform_type", "is_online", "datacenter.name", "datacenter.symbol", "ports.display_name", "vcc", "dracnet_ip", "account", "attached_devices", "is_windows", "offline_date", "attached_firewalls", "date_online", "account_domain_info.domain_name", "account_domain_info.add_userid_to_domain", "is_cluster" ) #adds password info if required If ($RackPW) { $ComputerAttributes += "root_password" $ComputerAttributes += "rack_password" } Return $ComputerAttributes } Function Get-COREDevicePSobject { Param( [Parameter ()][switch]$RackPW, [Parameter()]$Computers, [Parameter()][switch]$NoDRAC, [Parameter()][switch]$GetIP, #get ips from IP commander (adds 3 seconds) [Parameter ()]$IPs ) IF ($GetIP) { write-host "Getting IP information from IP commander - this will take around $($Computers.count * 3) seconds" } $DeviceList = @() ForEach ($Computer in $Computers) { #Ignore inactive computers IF ($Computer."status.name" -like "*no longer active*") { continue } #Get DRAC IP IF ($NoDRAC) { $DRAC_IP = $null } Else { IF ($Computer.dracnet_ip.load_value) { $DRAC_IP = Get-CoreIP -ID $($Computer.dracnet_ip.load_value) } else { $DRAC_IP = $null } } #Get IPs from IP commander IF ($GetIP) { $IPs = Get-IPsfromIPCommander -Device $Computer.number } [string]$name = $Computer.name $DevicePSO = [PSCustomObject]@{ Name = $Computer.name; Number = $Computer.number; IP = $Computer.primary_ip; PrivateIP=$Computer.primary_nat_ip; BackupIP=""; OSname=$Computer.os_name; NickName=$Computer.nickname; OStype=$Computer.os_type; PlatName=$Computer.platform_name; PlatType=$Computer.platform_type; Status=$Computer."status.name"; Datacenter=$Computer."datacenter.name"; DatacenterSymbol =$Computer."datacenter.symbol"; Ports=$Computer.ports.display_name; vCenter=$Computer.vcc; Offline=$Computer.offline_date; attached_firewalls = $Computer.attached_firewalls; "Account Name" = $Computer."account.name"; dracnet_ip = $DRAC_IP; Backup_IP = ""; attached_devices = $Computer.attached_devices; Account = $Computer.account.load_value; ServerName = ($name.Split(".")[0]); is_windows = $Computer.is_windows; offline_date = $Computer.offline_date; date_online = $Computer.date_online; dateonline = $Computer.date_online; Domain = $Computer."account_domain_info.domain_name"; IntensiveAddDomain = $Computer."account_domain_info.add_userid_to_domain"; is_cluster = $Computer."is_cluster"; ServiceNetGW = $IPs.ServiceNetGW ServiceNetIP = $IPs.ServiceNetIP ServiceNetNM = $IPs.ServiceNetNM PublicGW = $IPs.PublicGW PublicIP = $IPs.PublicIP PublicNM = $IPs.PublicNM PrivateGW = $IPs.PrivateGW PrivateNM = $IPs.PrivateNM } If ($RackPW) { Add-Member -InputObject $DevicePSO -NotePropertyName RackPass -NotePropertyValue $Computer.rack_password; Add-Member -InputObject $DevicePSO -NotePropertyName AdminPass -NotePropertyValue $Computer.root_password; } $DeviceList += $DevicePSO } Return $DeviceList } function Get-CoreDevicesAccount { Param( [Parameter(mandatory=$true)]$Account, [Parameter()]$limit = 25, [Parameter()][switch]$NoDRAC, [Parameter()][switch]$RackPW, [Parameter()][switch]$GetIP #get ips from IP commander (adds 3 seconds) ) #get our JSON If ($RackPW) { $obj = Get-COREDeviceJSON -Account $Account -RackPW -limit $limit } else { $obj = Get-COREDeviceJSON -Account $Account -limit $limit } $offset = 0 $Computers = @() do { #write to screen what we are doing write-host "Getting devices $offset to $($limit + $offset) from CORE..." #Update our offset in the JSON $obj.load_arg.offset = $offset #Convert it again $JSON = $obj | ConvertTo-Json #Query CORE $QueryResult = "" $QueryResult = (Get-CoreQuery -JSON $JSON).Result #Add result to array $Computers += $QueryResult $oldoffset = $offset $offset = $offset + $limit #debug #write-host "limit $limit" -ForegroundColor Yellow #write-host "QueryResult.created $(($QueryResult.created).count)" -ForegroundColor Yellow } Until (($QueryResult.created).count -lt $limit) $Params = @{ Computers = $Computers; } #Add additional params from the script If ($NoDRAC) { $Params.Add("NoDRAC", $true) } If ($RackPW) { $Params.Add("RackPW", $true) } If ($GetIP) { $Params.Add("GetIP", $true) } $ReturnedComputers = Get-COREDevicePSobject @params Return $ReturnedComputers } Function Get-COREDeviceJSON { Param( [Parameter()]$Device, [Parameter()]$Ticket, [Parameter()]$Account, [Parameter()]$Limit, [Parameter()][switch]$RackPW ) #get our computer attributes If ($RackPW) { $ComputerAttributes = Get-ComputerAttributes -RackPW } else { $ComputerAttributes = Get-ComputerAttributes } If ($Ticket) { #Create JSON object for ticket $obj = @( @{ "load_arg" = $ticket; "class" = "Ticket.Ticket"; "attributes" = @( "id", @{ "id" = "number" "attribute" = "computers" "subattributes" = $ComputerAttributes } ) } ) #Convert it $JSON = $obj | ConvertTo-Json -Depth 10 } If ($Account) { #Create JSON object $json = @( @{ "class" = "Computer.Computer"; "attributes" = $ComputerAttributes "load_arg" = @{ "class" = "Computer.ComputerWhere" "values" = @("account","=","$Account") "offset" = 0 "limit" = $limit } } ) } If ($Device) { #Create JSON object $obj = @( @{ "class" = "Computer.Computer"; "load_arg" = $Device "attributes" = $ComputerAttributes } ) #Convert it $JSON = $obj | ConvertTo-Json -Depth 10 } return $JSON } function Get-CoreDevicesTicket { Param( [Parameter(mandatory=$true)]$Ticket, [Parameter()][switch]$NoDRAC, [Parameter()][switch]$RackPW, [Parameter()][switch]$GetIP #get ips from IP commander (adds 3 seconds) ) #get our JSON If ($RackPW) { $JSON = Get-COREDeviceJSON -Ticket $Ticket -RackPW } else { $JSON = Get-COREDeviceJSON -Ticket $Ticket } #Query CORE $QueryResult = (Get-CoreQuery -JSON $JSON) #As we query subattributes when going via ticket, we need to expand the properties out $Computers = @() $ComputerList = $QueryResult.result.computers.subattributes | gm -MemberType NoteProperty | Select-Object Name ForEach ($Name in $ComputerList) { $Computers += $QueryResult.result.computers.subattributes."$($Name.Name)" } $Params = @{ Computers = $Computers; } #Add additional params from the script If ($NoDRAC) { $Params.Add("NoDRAC", $true) } If ($RackPW) { $Params.Add("RackPW", $true) } If ($GetIP) { $Params.Add("GetIP", $true) } $ReturnedComputers = Get-COREDevicePSobject @params Return $ReturnedComputers } function Get-IPsfromIPCommander { Param( [Parameter (Mandatory=$true)]$Device ) #Skip SSL errors [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} #Create the connection $WebService = New-WebServiceProxy -Uri "https://ipadmin.dcx.rackspace.com/ipadmin/ip_info/wsdl" -UseDefaultCredential #get IPs by device $IPs = $WebService.IpsByDevice("$device") #create psobject from results and return it $Output = New-Object PSObject #filter secondary IPs to get servicenet $servicenet = $IPs.secondary_ips | Where-Object {($_.descriptor -eq "servicesnet") -OR ($_.descriptor -eq "Managed Backup")} #servicenet Add-Member -InputObject $Output -MemberType NoteProperty -Name ServiceNetGW -Value $servicenet.gateway_ip Add-Member -InputObject $Output -MemberType NoteProperty -Name ServiceNetIP -Value $servicenet.ip_address Add-Member -InputObject $Output -MemberType NoteProperty -Name ServiceNetNM -Value $servicenet.netmask #public Add-Member -InputObject $Output -MemberType NoteProperty -Name PublicGW -Value $IPs.primary_ip[0].gateway_ip Add-Member -InputObject $Output -MemberType NoteProperty -Name PublicIP -Value $IPs.primary_ip[0].ip_address Add-Member -InputObject $Output -MemberType NoteProperty -Name PublicNM -Value $IPs.primary_ip[0].netmask #private Add-Member -InputObject $Output -MemberType NoteProperty -Name PrivateGW -Value $IPs.primary_ip[0].inside_local_gateway_ip Add-Member -InputObject $Output -MemberType NoteProperty -Name PrivateIP -Value $IPs.primary_ip[0].inside_local Add-Member -InputObject $Output -MemberType NoteProperty -Name PrivateNM -Value $IPs.primary_ip[0].inside_local_netmask return $output } function Get-CoreDevices{ Param( [Parameter ()][string] $Account, [Parameter ()][switch] $NoOutput, [Parameter ()][string] $Ticket, [Parameter ()][switch] $NoDRAC, [Parameter ()][switch] $RackPW ) IF ($Account) { $Params = @{ Account = $Account } If ($NoDRAC){$Params.Add("NoDRAC", $true)} If ($RackPW){$Params.Add("RackPW", $true)} Get-CoreDevicesAccount @Params } ELSEIF ($Ticket) { $Params = @{ Ticket = $Ticket } If ($NoDRAC){$Params.Add("NoDRAC", $true)} If ($RackPW){$Params.Add("RackPW", $true)} Get-CoreDevicesTicket @Params } ELSE { break } <# .SYNOPSIS RETIRED -> Use Get-CoreDevicesAccount and Get-CoreDevicesTicket .DESCRIPTION RETIRED -> Use Get-CoreDevicesAccount and Get-CoreDevicesTicket .EXAMPLE RETIRED -> Use Get-CoreDevicesAccount and Get-CoreDevicesTicket .EXAMPLE RETIRED -> Use Get-CoreDevicesAccount and Get-CoreDevicesTicket #> } function Get-CoreDevice { Param( [Parameter (Position=1, Mandatory=$true)] [string] $Device, [Parameter()][switch]$NoDRAC, [Parameter()][switch]$RackPW, [Parameter()][switch]$GetIP #get ips from IP commander (adds 3 seconds) ) #get our JSON If ($RackPW) { $JSON = Get-COREDeviceJSON -device $device -RackPW } else { $JSON = Get-COREDeviceJSON -device $device } #Query CORE $Computers = (Get-CoreQuery -JSON $JSON).Result $Params = @{ Computers = $Computers; } #Add additional params from the script If ($NoDRAC) { $Params.Add("NoDRAC", $true) } If ($RackPW) { $Params.Add("RackPW", $true) } If ($GetIP) { $Params.Add("GetIP", $true) } $ReturnedComputers = Get-COREDevicePSobject @params Return $ReturnedComputers <# .SYNOPSIS The Get-CoreDevice cmdlet retrieve details for specified device. The results will be output in format-list. The variable $Device will also be available at cmd line for use in scripts. .DESCRIPTION See synopsis. .EXAMPLE PS C:\Users\Administrator> Get-CoreDevice -Device 24645 This example shows how to retrieve device details #> } Function Get-CoreTicketDevices { Param ( [Parameter(Mandatory=$true)]$ticket = (Read-Host("Enter Ticket Number")) ) #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---Start of Get-CoreTicketDevices function" -noconsole #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---LEGACY FUNCTION IN USE!" -noconsole $DeviceList = Get-CoreDevices -Ticket $ticket return $DeviceList #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---End of Get-CoreTicketDevices function" -noconsole <# .SYNOPSIS Get-CoreTicketDevices is present to support legacy scripts Please use Get-CoreDevices -Ticket $ticket instead .DESCRIPTION See synopsis. .EXAMPLE Use Get-CoreDevices -Ticket $ticket instead #> } Function Get-CoreTicket { Param ( [Parameter(Mandatory=$true)]$ticket = (Read-Host("Enter Ticket Number")) ) #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---Start of Get-CoreTicket function" -noconsole #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---LEGACY FUNCTION IN USE!" -noconsole $DeviceList = Get-CoreDevices -Ticket $ticket return $DeviceList #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---End of Get-CoreTicket function" -noconsole <# .SYNOPSIS Get-CoreTicket is present to support legacy scripts Please use Get-CoreDevices -Ticket $ticket instead .DESCRIPTION See synopsis. .EXAMPLE Use Get-CoreDevices -Ticket $ticket instead #> } Function Get-CoreTicketContents { Param ( [Parameter(Mandatory=$true)]$ticket = (Read-Host("Enter Ticket Number")) ) #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---Start of Get-CoreTicketContents function" -noconsole #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "ticket = $ticket" -noconsole $obj = @( @{ "class" = "Ticket.Ticket"; "attributes" = @( "id", "account", "subject", "status", "messages", "is_scheduled_service", "assignee", "queue", "difficulty" ) } ) $obj[0]['load_arg'] = $ticket $JSON = $obj | ConvertTo-Json Validate-CoreToken $result = "" $result = Get-CoreQuery -JSON $JSON #Expand the assignee ID to the actual name Try{ Add-Member -InputObject $result.result -MemberType NoteProperty -Name Assignee_ID -Value $($result.result.assignee.load_value) $result.result.assignee = (Get-CoreContact -ID $result.result.assignee.load_value).Name } Catch{ #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "ERROR TRAP in Get-CoreTicketContents" -noconsole } Return $result.result #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---End of Get-CoreTicketContents function" -noconsole } Function Get-CoreTicketMessage { Param ( [Parameter(Mandatory=$true)]$ID ) #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---Start of Get-CoreTicketMessage function" -noconsole #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "ID = $ID" -noconsole $obj = @( @{ "class" = "Ticket.Message"; "attributes" = @( "text", "is_visible", "is_customer", "date", "private", "contact", "source", "id", "contact" ) } ) $obj[0]['load_arg'] = $ID $JSON = $obj | ConvertTo-Json -Depth 10 Validate-CoreToken $result = "" $result = Get-CoreQuery -JSON $JSON Return $result.result #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---End of Get-CoreTicketMessage function" -noconsole } Function Get-AccountTeam { Param ( [Parameter(Mandatory=$true)]$Account ) #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---Start of Get-AccountTeam function" -noconsole #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "Account = $Account" -noconsole $obj = @( @{ "class" = "Account.Account"; "attributes" = @( "account_exec", "primary_lead_tech", "business_development", "am_queue" ) } ) $obj[0]['load_arg'] = $Account $JSON = $obj | ConvertTo-Json -Depth 10 $result = "" $result = Get-CoreQuery -JSON $JSON $Contacts = @() Try{ $Contacts += Get-CoreContact -ID $result.result.primary_lead_tech.load_value } Catch { #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "lead tech not found, this is probably intensive managed" -type error $Contacts += $false } $Contacts += Get-CoreContact -ID $result.result.account_exec.load_value $Contacts += Get-CoreContact -ID $result.result.business_development.load_value $Contacts += $result.result.am_queue.id Return $Contacts #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---End of Get-AccountTeam function" -noconsole } Function Get-CoreContact { Param ( [Parameter(Mandatory=$true)]$ID ) #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---Start of Get-CoreContact function" -noconsole #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "ID = $ID" -noconsole $obj = @( @{ "class" = "Contact.Contact"; "attributes" = @( "first_name", "last_name", "name", "primary_email", "employee_userid", "id", "teams", "title", "org", "ldap_groups", "individual", "departments", "imaway" ) } ) $obj[0]['load_arg'] = $ID $JSON = $obj | ConvertTo-Json -Depth 10 Validate-CoreToken $result = "" $result = Get-CoreQuery -JSON $JSON Return $result.result #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---End of Get-CoreContact function" -noconsole } Function Get-CoreEmail { Param ( [Parameter(Mandatory=$true)]$ID ) #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---Start of Get-CoreEmail function" -noconsole #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "ID = $ID" -noconsole $obj = @( @{ "class" = "Contact.Email"; "attributes" = @( "address" ) } ) $obj[0]['load_arg'] = $ID $JSON = $obj | ConvertTo-Json -Depth 10 Validate-CoreToken $result = "" $result = Get-CoreQuery -JSON $JSON Return $result.result #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---End of Get-CoreEmail function" -noconsole } Function Set-CoreTicketAssignee { Param ( [Parameter(Mandatory=$true)]$ID, [Parameter(Mandatory=$true)]$Ticket ) Invoke-RestMethod -Uri "https://ws.core.rackspace.com/ctkapi/attribute/Ticket/$ticket/assignee" -Method "Post" -Headers @{"X-Auth"=$global:token} -Body "$ID" | Out-Null } Function Set-CoreTicketQueue { Param ( [Parameter(Mandatory=$true)]$Ticket, [Parameter(Mandatory=$true)]$queue ) Invoke-RestMethod -Uri "https://ws.core.rackspace.com/ctkapi/attribute/Ticket/$ticket/queue" -Method "Post" -Headers @{"X-Auth"=$global:token} -Body "$queue" | Out-Null #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---End of Set-CoreTicketQueue function" -noconsole } Function Get-CoreTicketDetails { Param ( [Parameter(Mandatory=$true)]$Ticket ) #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---Start of Get-CoreTicketDetails function" -noconsole #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "Ticket = $Ticket" -noconsole $obj = @( @{ "class" = "Ticket.Ticket"; "attributes" = @( "account", "subject", "status", "messages", "is_scheduled_service", "superticket" ) } ) $obj[0]['load_arg'] = $Ticket $JSON = $obj | ConvertTo-Json -Depth 10 Validate-CoreToken $result = "" $result = Get-CoreQuery -JSON $JSON Return $result.result #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---End of Get-CoreTicketDetails function" -noconsole } Function Get-CoreIP { Param ( [Parameter(Mandatory=$true)]$ID ) #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---Start of Get-CoreIP function" -noconsole #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "ID = $ID" -noconsole $obj = @( @{ "class" = "IPSpace.IPAssignment"; "attributes" = @( "ip_address" ) } ) $obj[0]['load_arg'] = $ID $JSON = $obj | ConvertTo-Json -Depth 10 Validate-CoreToken $result = "" $result = Get-CoreQuery -JSON $JSON Return $result.result.ip_address #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---End of Get-CoreIP function" -noconsole } Function Set-CoreTicketDifficulty { Param ( [Parameter(Mandatory=$true)]$Difficulty, [Parameter(Mandatory=$true)]$Ticket ) #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---Start of Set-CoreTicketDifficulty function" -noconsole #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "Difficulty = $Difficulty" -noconsole #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "Ticket = $Ticket" -noconsole Invoke-RestMethod -Uri "https://ws.core.rackspace.com/ctkapi/attribute/Ticket/$ticket/difficulty" -Method "Post" -Headers @{"X-Auth"=$global:token} -Body "$Difficulty" | Out-Null #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---Start of Set-CoreTicketDifficulty function" -noconsole } Function Set-CoreTicketAssigneeByLogin { Param ( [Parameter(Mandatory=$true)]$Ticket ) #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---Start of Set-CoreTicketAssigneeByLogin function" -noconsole #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "Ticket = $Ticket" -noconsole $JSON=@" [ { "class": "Ticket.Ticket", "load_arg": "$Ticket", "set_attribute": { "assignee": { "class": "Contact.Contact", "load_arg": { "class": "Contact.ContactWhere", "values": [ [ "employee_userid", "=", "$([Environment]::UserName)" ] ] } } } } ] "@ Validate-CoreToken $result = "" $result = Get-CoreQuery -JSON $JSON #Return $result #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---End of Set-CoreTicketAssigneeByLogin function" -noconsole } Function Add-COREDeviceToTicket { Param( [Parameter(Mandatory=$true)]$Device, [Parameter(Mandatory=$true)]$ticket ) $obj = @( @{ "class" = "Ticket.Ticket"; "method" = "addComputer"; "args" = @( "$Device" ) } ) $obj[0]['load_arg'] = $ticket $JSON = $obj | ConvertTo-Json -Depth 10 $response = Invoke-RestMethod -Uri "https://ws.core.rackspace.com/ctkapi/query" -ContentType "application\json" -Method "Post" -Headers @{"X-Auth"=$global:token} -Body $JSON Return $response.Success } Function Update-CoreTicket{ Param( [Parameter(Mandatory=$true)][string]$Ticket, [Parameter(Mandatory=$true)][string]$Message, [Parameter()][Int]$Source=4, [Parameter()][Int]$Private=1, [Parameter()][Int]$source_contact=0, [Parameter()][Int]$send_message_text=0, [Parameter()][Int]$contact=0, [Parameter()][Int]$send_email=0, [Parameter()][Int]$message_time, [Parameter()][Int]$has_bbcode=0 ) <#Source source 1 Customer [Phone Call] source 2 Customer [MyRackspace] source 3 Rackspace Employee source 4 CORE source 5 Customer [Genie] source 6 Customer [Mass Ticket] source 7 Customer [Walk-Up] source 8 Customer [EZCASH] source 9 Customer [Email] source 10 Customer [Other] source 11 Customer [Chat Support] source 12 Customer [RunBook] source 13 Customer [RackerApp] #> Validate-CoreToken $unixEpochStart = new-object DateTime 1970,1,1,0,0,0,([DateTimeKind]::Utc) $message_time = [int]([DateTime]::UtcNow - $unixEpochStart).TotalSeconds #update JSON with variables $JSON = ' [ { "class": "Ticket.Ticket", "load_arg": "'+$Ticket +'", "method": "addMessage", "args": [ "'+$Message+'", '+$Source+', '+$Private+', '+$source_contact+', '+$send_message_text+', '+$contact+', '+$send_email+', '+$message_time+', '+$has_bbcode+' ] } ] ' $result = Get-CoreQuery -JSON $JSON #Check CORE confirms update was a success, or write failure to screen IF($result.Success -ne "True") { Write-host "failed to update ticket" } #Update-Logfile -logfilepath $Global:CTKCoreLogPath -Message "---End of Update-CoreTicket function" -noconsole <# .SYNOPSIS The Update-Ticket cmdlet will update tickets in CORE .DESCRIPTION See synopsis. private: Boolean determining if the Contact cannot see it. source_contact: Who created the message. send_message_text: Boolean determining if text of message should be included in e-mail. has_bbcode: Boolean value informing ticket renderer there is BBCode inside .Parameter Message The ticket update message. Example: Update-Ticket -Ticket "131119-05919" -Message "update test from powershell" .Parameter Source The ticket update source. I wouldn't change this unless you need too. #https://ws.core.rackspace.com/ctkapi/browse/Ticket/Source #Using a customer source forces ticket to be public then marked as private .Parameter Private Private or public update. If you do a public update on a private ticket, CORE will automatically change it Private by default (0) Example: Update-Ticket -Ticket "131119-05919" -Message "Public update test from powershell" -Private 0 .Parameter source_contact Who created the message. Do not change this unless you have a reason too as it defaults to your login name .Parameter send_message_text Boolean determining if text of message should be included in e-mail. Do not change this unless you have a reason too .Parameter contact Do not change this unless you have a reason too .Parameter send_email Do not change this unless you have a reason too .Parameter message_time Do not change this unless you have a reason too .Parameter has_bbcode Enable BBCode in the ticket Example: Update-Ticket -Ticket "131119-05919" -Message "Public update test from powershell" -has_bbcode 1 .EXAMPLE Update-Ticket -Ticket "131119-05919" -Message "update test from powershell" This example shows how to add a private update .EXAMPLE Update-Ticket -Ticket "131119-05919" -Message "Public update test from powershell" -Private 0 This example shows how to add a public update .EXAMPLE Update-Ticket -Ticket "131119-05919" -Message "Public update test from powershell" -Private 0 -has_bbcode 1 This example shows how to add a public update with BBCode .Notes Written by Martin Howlett - martin.howlett@rackspace.co.uk #> } Function Get-CoreTicketSummary { <# .Synopsis Summary of all tickets in a given time frame for an account .Description The Get-CoreTicketSummary cmdlet will pull a list of all tickets for a customer within a given time frame. .Example Get-CoreTicketSummary -Account 24645 -StartDate "2015-01-01- 00:00:00" -EndDate "2015-01-31 23:59:59" This example shows how to retrive a list of tickets for the customer between 1st Jan 2015 00:00:00 and 31st Jan 2015 at 23:59:59 .Example Get-CoreTicketSummary -Account 24645 This example shows how to retrive a list of tickets for the customer between 1st day of the month 00:00:00 to the last day of the month at 23:59:59 for the last month. For example if it was March 18th, this command would pull everything from 1st-28th Feburary. #> Param( [Parameter(Mandatory=$true)][string]$Account, [Parameter()][string]$StartDate, [Parameter()][string]$EndDate, [Parameter()][switch]$UseLastMonth ) If($UseLastMonth){ $date = Get-Date $numMonthsAgo = -1 $startofmonth = Get-Date $date -day 1 -hour 0 -minute 0 -second 0 $endofmonth = (($startofmonth).AddMonths(1).AddSeconds(-1)) $firstDayOfMonth = $startofmonth.AddMonths($numMonthsAgo) $lastDayOfMonth = $endofmonth.AddMonths($numMonthsAgo) } $limit = 50 $offset = 0 $result = @() do { $JSON = @" [ { "class": "Ticket.Ticket", "load_arg": { "class": "Ticket.TicketWhere", "values": [ [ "account", "=", "$Account" ], "&", [ "created", ">", "$($firstDayOfMonth.ToString("yyyy-MM-dd HH:mm:ss"))" ], "&", [ "created", "<", "$($LastDayOfMonth.ToString("yyyy-MM-dd HH:mm:ss"))" ] ], "limit": $limit, "offset": $offset }, "attributes": [ "number", "status.name", "subject", "source", "created", "creator.name", "severity.name", "classification.name", "category.name", "subcategory.name", "last_response_date", "computers", { "attribute": "computers", "subattributes": [ "name" ] } ] } ] "@ Validate-CoreToken $QueryResult = "" $QueryResult = (Get-CoreQuery -JSON $JSON).Result $result += $QueryResult $offset = $offset + $limit }Until (($QueryResult.created).count -lt $limit) $Tickets = @() foreach($Ticket in $result){ [string]$lstComputers = "" $arrComp = @() ForEach ($Comp in $Ticket.Computers.subattributes){ [string]$strComp = $Comp.name $arrComp += $strComp.Split(".")[0] } $lstComputers = $arrComp -join " : " $Tickets += [PSCustomObject]@{ TicketID=$Ticket.number; Status=$Ticket."status.name"; Subject=$Ticket."subject"; Created=$Ticket.created; Creator=$Ticket."creator.name"; Severity=$Ticket."severity.name"; Classification=$Ticket."classification.name"; Category=$Ticket."category.name"; SubCategory=$Ticket."subcategory.name"; Last_Response_Date=$Ticket.last_response_date; Source=$Ticket.source.name; Devices=$lstComputers; } } Return $Tickets } #Use with CTKCoreTestCode.ps1 #Function you can use to test/troubleshoot Json. #Author:Mark Wichall Function Test-CTKJson { Param ( [Parameter()]$JSON ) Validate-CoreToken $result = "" $result = Get-CoreQuery -JSON $JSON return $result.result } Function Get-CoreSSLCertificate { Param ( [Parameter()]$ID, [Parameter()]$Ticket ) #$ID = "150117-06312" #$ID = "2105454" IF ($ID) { $loadArg = $ID } ELSE { $loadArg = $Ticket } $obj = @( @{ "class" = "Certificate.Certificate"; "attributes" = @( "account", "active", "cert", "company_name", "csr", "customer_ticket", "domain_name", "end_date", "id", "order_number", "pretty_end_date", "private_key", "start_date", "state", "status", "ticket", "product_type", "computers" ) } ) $obj[0]['load_arg'] = $loadArg $JSON = $obj | ConvertTo-Json -Depth 10 Validate-CoreToken $result = "" $result = Get-CoreQuery -JSON $JSON Return $result.result <# $JSON=@" [ { "class": "Certificate.Certificate", "load_arg": { "class": "Certificate.CertificateWhere", "values": [ [ "ticket", "=", "140909-04864" ] ], "limit": 200, "offset": 0 }, "attributes": [ "id" ] } ] "@ #> } Function Get-CoreDeviceSKU { Param ( [Parameter(Mandatory=$true)]$Device ) $JSON = @" [ { "class": "Computer.Computer", "load_arg": $Device, "attributes": [ "number", { "attribute": "parts", "subattributes": { "Description": "ctk_product.description", "sku": "sku_number", "label": "display_label", "modified": "modified", "part_attributes": { "attribute": "partributes", "subattributes": [ "value", "sku_attribute.description" ] } } } ] } ] "@ Validate-CoreToken $result = "" $result = Get-CoreQuery -JSON $JSON $SKUs = $result.result.parts.subattributes $SKUarr = @() ForEach ($Sku in $SKUs) { $temp = "" $temp = New-Object PSObject -Property @{ SKU = $Sku.Sku Value = $Sku.part_attributes.subattributes.value ValueLabel = $Sku.part_attributes.subattributes."sku_attribute.description" Label = $sku.label Description = $sku.Description Server = $Device } $SKUarr += $temp } Return $SKUarr } Function New-CoreSubTicket{ Param( [Parameter(Mandatory=$true)][string]$MasterTicket, [Parameter(Mandatory=$true)][string]$Subject, [Parameter(Mandatory=$true)][string]$FirstComment, [Parameter()][Int]$Queue=26, [Parameter()][Int]$priority=1, [Parameter()][Int]$severity=1, [Parameter()][array]$computers, [Parameter()][Int]$is_private_message=1, [Parameter()][Int]$is_private_ticket=1 ) $obj = @{ "class"= "Ticket.Ticket"; "load_arg"= "$MasterTicket"; "method"= "addSubTicket"; "args"= @( "$Subject", "$FirstComment", "$Queue", $priority, $severity, $computers, $is_private_message, $is_private_ticket ) } $JSON = $obj | ConvertTo-Json -Depth 10 Validate-CoreToken $result = "" $result = Get-CoreQuery -JSON $JSON return $result.result.load_value <# .SYNOPSIS .DESCRIPTION See synopsis. .Notes Written by Martin Howlett - martin.howlett@rackspace.co.uk #> } Function Get-ClusterHostfile{ param( [Parameter()]$Devices ) #Create the arrays we will use $Nodes =@() $VirtualComputers =@() $NodesBackup =@() $VirtualComputersBackup =@() $Heartbeats =@() $Blank =@() IF ($HeartbeatIP.Length -lt 1) {$HeartbeatIP = 0} #The domain is often incorrect on virtual servers, so we get the domain for the first node and use that $Node1 = ($devices | Where-Object {$_.is_cluster -ne $True})[0] $Domain = $Node1.Domain ForEach ($Device in $Devices) { #we null values first to stop errors with previous loops $ServiceNetIP = $null $PrivateIP = $null $Account = $null $Number = $null $NoBackup = $null $Account = $Device.Account $Number = $Device.number $Name = $Device.ServerName write-host "Generating hostfile entries for $($Device.ServerName), please wait..." -ForegroundColor Cyan if($Device.Domain -ne $domain){ $DomainError = $true write-host "ERROR! Domain doesn't match for all devices so using domain from first node. Please manually check as CORE could be incorrect" -ForegroundColor Red } #check name and exclude if NT or MSDTC If (($Name -like "*-NT*") -OR ($Name -like "*MSDTC*")){ $NoBackup = $true } $IPs = Get-IPsfromIPCommander -Device $Number $ServiceNetIP = $IPs.ServiceNetIP $PrivateIP = $IPs.PrivateIP #check to make sure its not blank If((-NOT $ServiceNetIP) -AND (-NOT $NoBackup)){ $ServiceNetIP = "BLANK" $Blank += $Number write-host "ERROR! Blank ServiceNet for $name, please manually add" -ForegroundColor Red } #check if its a virtual cluster device IF ($Device.is_cluster){ #build the line for the host file for the nat ip $VirtualComputers += "$PrivateIP $Name $Name.$Domain" IF (-NOT $NoBackup){ #and the line for the backup ip $VirtualComputersBackup += "$ServiceNetIP $Account-$Number" } #if its not a virtual device, it must be a node }ELSE{ #build the line for the host file for the nat ip $Nodes += "$PrivateIP $Name.$Domain" IF (-NOT $NoBackup){ #and the line for the backup ip $NodesBackup += "$ServiceNetIP $Account-$Number" } #increase the heartbeat IP by 1 and build the heartbeat IP $HeartbeatIP ++ $Heartbeats += "10.10.10.$HeartbeatIP heartbeat$HeartbeatIP" } } #Create the temp text file for the hostfile #$Hostfiletemp = "C:\RS-PKGS\hostfile.txt" #New-Item $Hostfiletemp -Type File -Force | Out-Null #Write out to the new lines to an array $newlines = @() If($Blank){$newlines += "WARNING! BLANK SERVICENET DETECTED FOR $($Blank -join ",")!!"} If($DomainError){$newlines += "WARNING! DOMAIN IS NOT THE SAME FOR ALL DEVICES, USING DOMAIN FROM 1ST NODE!!"} $newlines += " " $newlines += " " $newlines += "#Node IPs" $newlines += "$(($Nodes) | Out-String)" $newlines += "#Cluster device IPs" $newlines += "$($VirtualComputers | Out-String)" $newlines += "#Heartbeat IPs" $newlines += "$($HeartBeats | Out-String)" $newlines += "#Node backup IPs" $newlines += "$($NodesBackup | Out-String)" $newlines += "#Cluster device backup IPs" $newlines += "$($VirtualComputersBackup | Out-String)" #Add them to the temp file we created #Add-content $Hostfiletemp -value $newlines | Out-Null #Update-Hostfile -newlines $newlines return $newlines } Function New-CoreTicket{ Param( [Parameter(Mandatory=$true)][Int]$Account, [Parameter(Mandatory=$true)][Int]$Queue=26, #Intensive(All teams) [Parameter()][Int]$subcategory=13376, #Windows - Other [Parameter()][Int]$source=3, #Rackspace Employee [Parameter()][Int]$severity=1, #Standard [Parameter(Mandatory=$true)][String]$subject, [Parameter(Mandatory=$true)][String]$text, [Parameter()]$computer_list=$null, [Parameter()][Int]$is_private_message=1, [Parameter()]$contact_list=$null, [Parameter()]$assignee=$null, [Parameter()]$source_contact=$null, [Parameter()][Int]$is_private_ticket=1, [Parameter()][Int]$send_message_text=0, [Parameter()]$status=$null, [Parameter()]$contact_email_type=$null, [Parameter()][Int]$priority=1, [Parameter()]$product_suite_name=$null, [Parameter()]$product_name=$null, [Parameter()]$action_name=$null, [Parameter()]$classification=$null, [Parameter()]$message_time=$null, [Parameter()]$required_receipients=$null, [Parameter()][Int]$has_bbcode=0 ) $obj = @{ "class"= "Account.Account"; "load_arg"= "$Account"; "method"= "addTicket"; "args"= @( $queue, $subcategory, $source, $severity, $subject, $text, $computer_list, $is_private_message #I cant get core to work with a null contact list so i cant add any more options #$contact_list #$assignee, #$source_contact, #$is_private_ticket, #$send_message_text #$status, #$contact_email_type, #$priority, #$product_suite_name=, #$product_name, #$action_name, #$classification, #$message_time, #$required_receipients, #$has_bbcode ) } $JSON = $obj | ConvertTo-Json -Depth 10 Validate-CoreToken $result = "" $result = Get-CoreQuery -JSON $JSON return $result.result.load_value <# .SYNOPSIS .DESCRIPTION See synopsis. .Notes Written by Martin Howlett - martin.howlett@rackspace.co.uk #> } #Function to test if number is device and return true/false Function Test-COREDevice{ Param( [Parameter (Mandatory=$true)]$Device ) $obj = @( @{ "class" = "Computer.Computer"; "attributes" = @( "name" ) } ) $obj[0]['load_arg'] = $Device $JSON = $obj | ConvertTo-Json -Depth 10 $result = "" $result = Get-CoreQuery -ErrorAction SilentlyContinue -JSON $JSON if( $result.result){ return $true }else{ return $false } }