#################### ComputerWhere functions - BEGIN #################### #region Function Find-CoreComputer { <# .SYNOPSIS Function for searching for computers in CORE via CTKAPI .DESCRIPTION Function for doing a computer based search via the Core API (CTKAPI) You can specify multiple search criteria to focus your search for various criteria You essentially need to choose your search terms and our output. Output is set by the params Attributes and CustomAttributes. You can ignore these and a default set of computer attributes will be returned, like nickname and number. If you need more information from your search, add attribute groups with the attribute param. You can als add custom attributes if you want to get even more granular See the help for the attribute param for this function for more information Input is set by the other params, simply select them and fill in the criteria In the background this function is using the where statement on the ticket class against the CTKAPI and parsing the output. It will also: - Manage your token, prompting for new one if it expires - Parse output into a Powershell friendly output - If the query is too large it will automatically start breaking it out into smaller ones - Has throttling protection to stop CTKAPI erroring out Make your search as specific as possible, so use as many function parameters as you can to limit your search. It will be faster and you will get far more useful data back. Dont just search for all computers on an account and filter in powershell, its SLOW! There are many, many variations of search, returning lots of data. Check examples section for some inspiration as well as the param help for details on the search types Input for a single search criteria is limited to 249. This is a CTKAPI limitation. If you want to search for more then 249 of a single thing, say, 500 computers, you will need to split the input up before you pass it to this function as any input will not accept more then 249 Try to limit the number of attributes you return, in particular the group "SKUs" These are actually subattributes, which can be really slow as it is puts more work on the CTKAPI so avoid using these unless you absolutly have too! It is best practice to limit the attribute groups you use as well. While pretty small, all of these will have an effect on the time a query takes See the help for Get-CoreComputerAttributes and the attribute param for this function for more information. Make sure you check the CustomAttribute help as well, as this may be useful for limiting your querys Throttling will stop you performing too many queries in a time frame, so if you see a pause during a query, this is to stop the CTKAPI rejecting your query .PARAMETER Accounts Optional Integer Account numbers that the tickets will be under, can be array. (Max 249) If you want a single account, just pass the single account number Validated against regex Example: 1103359 Example: 965448 Example: @(1103359,965448) .PARAMETER Computers Optional Integer Computer numbers of the devices to retrun information on (Max 249) If you want a single computer, just pass the single computer number Validated against regex Example: 560570 Example: 560559 Example: @(560570,560559) .PARAMETER StatusName Optional Name fo the status a computer is in e.g. "online/complete" If this option is used a warning will be flagged to state it's more efficient to use StatusID as this required less looks up as status name has to be looked up and the id retruned. You can use the following command to check the list of valid statusnames and the statusid to use when writting a query Find-CoreAttributeValues -Class 'Computer' -SubClass 'Status' -ReturnAll .PARAMETER StatusId Optional Prefreable to use StatusID oposed to StatusName as it requires only a single lookup, see statusname To check the list of avalible statusids run the following command Find-CoreAttributeValues -Class 'Computer' -SubClass 'Status' -ReturnAll .PARAMETER StatusGroup Optional Returns devices in the status group specified The only valid options are online and offline, the other groups have not been included as they overlap with online and offline and add complexity Validated against regex Example: online Example: offline .PARAMETER Attributes Specify groups of computer attributes to return with your search There is a default list of attributes that will always be returned, but you can specify additional groups For example, if you wanted network information on device 560559, you would do this: Find-CoreComputer -Computers @(560559) -Attributes Network Use the following command to return all computer attributes and their group names Get-CoreComputerAttributes -PrintAttributes You can also use the CustomAttributes param to return individual attributes .PARAMETER CustomAttributes Hashtable of additional attributes to return with your search There is a default list of computer attributes that will always be returned You can specify additional groups using the Attribute paramter (see Attribute param help) If you want to just return 1 or 2 additional params, use this parameter. You will need to provide a hashtable of attributes, where the friendly name is the key and the value is the Core API search For example, if you wanted to return the contract ID but didnt want to use the Implementation attribute group, you could use this: $Result = Find-CoreComputer -Computers @(560559) -CustomAttribute @{"contract"="contract.id"} $result.result.contract You can see that PoshCore converts the core api value (contract.id) into the friendly value You can return more then 1 custom value, just supply them in the same hashtable: $Result = Find-CoreComputer -Computers @(560559) -CustomAttribute @{"contract"="contract.id" ; "segment_queue"="segment_queue.name"} Returns: segment_queue : Intensive (All Teams) name : 560559-DB1.rackspace.com status_name : Online/Complete number : 560559 contract : 87732 datacenter_symbol : LON3 nickname : ttt account_name : International Enterprise Support Test Account account_id : 1103359 You are encouraged to use the attribute groups first before turning to custom attributes, as its simpler You can use the command Get-CoreComputerAttributes -PrintAttributes to get a list of attributes and their CustomAttribute syntax You can also get more attributes here: https://ws.core.rackspace.com/ctkapi/browse/Computer/Computer .PARAMETER FullObject Optional Switch Retuns the full object from core (.result) plus the time taken by the query,load args,limit,offset,count of objects retruned,etc If switch is not specified the .result content are only returned i.e. the data from core which is the default. Example of retruning Full object count : 1 load_arg : @{limit=100; values=System.Object[]; class=Ticket.TicketWhere; offset=0} limit : 100 result : {@{Computers=System.Object[]; queue_name=INTL Windows; number=161201-08495; private=0;....}} offset : 0 class : Ticket.Ticket QueryTime : 0.7459383 .EXAMPLE Return all computers in account 1103359 $Result = Find-CoreComputer -Accounts @(1103359) .EXAMPLE Return all computers in account 1103359 along with their domain info $AllComputers = Find-CoreComputer -Accounts @(1103359) -Attributes Domain .EXAMPLE Return password information for computer 560559 $AllComputers = Find-CoreComputer -Computers 560559 -Attributes Password .EXAMPLE Return password information for computer 560559 and 560570 and a custom attribute for their contract ID $Result = Find-CoreComputer -Computers @(560559,560570) -Attributes Network -CustomAttributes @{"contract"="contract.id"} .EXAMPLE Return computers with a online/complete status e.g. statusid 12 $Result = Find-CoreComputer -Accounts @(1103359) -statusid 12 .EXAMPLE Return computers with an online status e.g. status that are classed as online in the statusgroup online $Result = Find-CoreComputer -Accounts @(1103359) -statusgroup online .OUTPUTS The result object from Core .NOTES Written by Martin Howlett / Mark Wichall #> [CmdletBinding(DefaultParameterSetName="Default")] Param ( [Parameter(ParameterSetName="Default")] [Parameter(ParameterSetName='Status Set 1')] [Parameter(ParameterSetName='Status Set 2')] [Parameter(ParameterSetName='Status Set 3')] [ValidatePattern("^[0-9]{4,9}$")] [ValidateNotNullOrEmpty()] [ValidateCount(1,249)] [Int[]]$Accounts, [Parameter(ParameterSetName="Default")] [Parameter(ParameterSetName='Status Set 1')] [Parameter(ParameterSetName='Status Set 2')] [Parameter(ParameterSetName='Status Set 3')] [ValidatePattern("^[0-9]{6}$")] [ValidateNotNullOrEmpty()] [ValidateCount(1,249)] [Int[]]$Computers, [Parameter(ParameterSetName='Status Set 1')] [ValidateNotNullOrEmpty()] [ValidateCount(1,249)] [String[]]$StatusName, #valid values are -1,1 to 73, 185 to 195 (validation below -1, 1-9, 10-69, 70-73, 185-189, 190-195) [Parameter(ParameterSetName='Status Set 2')] [ValidateScript({$_ -eq "-1" -or $_ -match {^[1-9]{1}$} -or $_ -match {^[1-6]{1}[0-9]{1}$} -or $_ -match {^[7]{1}[0-3]{1}$} -or $_ -match {^[1]{1}[8]{1}[5-9]{1}$} -or $_ -match {^[1]{1}[9]{1}[0-5]{1}$} })] [ValidateCount(1,249)] [Int[]]$StatusId, [Parameter(ParameterSetName='Status Set 3')] [Validateset("Online","Offline")] [String]$StatusGroup, [Parameter(ParameterSetName="Default")] [Parameter(ParameterSetName='Status Set 1')] [Parameter(ParameterSetName='Status Set 2')] [Parameter(ParameterSetName='Status Set 3')] [ValidateRange(1,249)] [int]$QueryLimit = 100, [Parameter(ParameterSetName="Default")] [Parameter(ParameterSetName='Status Set 1')] [Parameter(ParameterSetName='Status Set 2')] [Parameter(ParameterSetName='Status Set 3')] [Validateset("Default","Network","Drac","Bandwidth","Attached","Backup","Storage","Misc","Domain","Implementation","Is","Os","Password","Skus","StatusLogs")] [String[]]$Attributes, [Parameter(ParameterSetName="Default")] [Parameter(ParameterSetName='Status Set 1')] [Parameter(ParameterSetName='Status Set 2')] [Parameter(ParameterSetName='Status Set 3')] [ValidateNotNullOrEmpty()] [Hashtable]$CustomAttributes, [Parameter(ParameterSetName="Default")] [Parameter(ParameterSetName='Status Set 1')] [Parameter(ParameterSetName='Status Set 2')] [Parameter(ParameterSetName='Status Set 3')] [Switch]$FullObject ) Begin { Write-Verbose "Start of $($MyInvocation.MyCommand)" } Process { #computer status if($StatusName) { #Validate the input $StatusName = Get-UniqueArray -InputArray $StatusName [Array]$StatusId = $null ForEach ($Name in $StatusName) { #Convert our StatusName into a QueueID Write-Verbose "StatusName parameter supplied ($StatusName)" #find the queue attrbute values $Status = $null $Status = Find-CoreAttributeValues -Class "Computer" -SubClass "Status" -SearchName $Name if(-not $Status.ID) { Write-Warning "Check valid statusname options using Find-CoreAttributeValues -Class 'Computer' -SubClass 'Status' -ReturnAll" Throw "PoshCore - Find-CoreComputer - Could not find a match for statusname ($StatusName)" } $StatusId += $Status.ID Write-Verbose "Found Status ID $StatusId from $Name" Write-Warning "For best performance you should use Status ID and not Status name. Status name is good when you are not sure on ID. Use this parameter -> -StatusId $StatusId" } } #Create the dictionary that will hold our query arguments [Hashtable]$SearchTerms = @{} #Add account numbers if($Accounts) { #Validate the input $Accounts = Get-UniqueArray -InputArray $Accounts #Add to our hashtable $SearchTerms.Add("Accounts",@("account","in", [System.Collections.ArrayList]$Accounts)) Write-Verbose "Added Accounts: $($Accounts -join ",")" } #Add computer numbers if($Computers) { #Validate the input $Computers = Get-UniqueArray -InputArray $Computers #Add to our hashtable $SearchTerms.Add("Computers",@("number","in", [System.Collections.ArrayList]$Computers)) Write-Verbose "Added Computers: $($Computers -join ",")" } #computer status if($StatusId) { #Validate the input $StatusId = Get-UniqueArray -InputArray $StatusId #Add to our hashtable $SearchTerms.Add("Status",@("status","in", [System.Collections.ArrayList]$StatusId)) Write-Verbose "Added Status: $($StatusId -join ",")" } #computer status if($StatusGroup) { Switch ($StatusGroup) { "Online" {$Status = @("online")} "Offline" {$Status = @("offline")} } #Add to our hashtable $SearchTerms.Add("Status_Group",@("status_group","in", [System.Collections.ArrayList]$Status)) Write-Verbose "Added Status: $($Status -join ",")" } #if we dont have any search terms, throw an error if($SearchTerms.keys.count -eq 0) { Throw "No criteria selected for Computer search" } #Add our list of user selected attributes [Hashtable]$CoreComputerAttributes = @{} if($Attributes) { $CoreComputerAttributes.Add("Attributes",$Attributes) } $QueryAttributes = Get-CoreComputerAttributes @CoreComputerAttributes #Build our variables for the Core where statement handler [Hashtable]$WrapperParams = @{ SearchTerms = $SearchTerms Attributes = $QueryAttributes Class = "Computer" QueryLimit = $QueryLimit } #if the user has supplied a custom attribute hashtable, we pass this to our where wrapper if($CustomAttributes) { $WrapperParams.Add("CustomAttributes",$CustomAttributes) } $result = Invoke-CoreWhereWrapper @WrapperParams #Retruns the .result value as default, full object retruned if $FullObject switch used. If (-not $FullObject) { $result = $result.result } return $result } End { #Log to appstats Set-LogtoAppstats -FunctionID "Find-CoreComputer" -AppID "PoshCore" Write-Verbose "End of $($MyInvocation.MyCommand)" } } Function Get-CoreComputerAttributes { <# .SYNOPSIS Returns attributes for ticketwhere queries .DESCRIPTION Creates a hashtable of attributes used with computerwhere statements in Core Using the attribute switch you can build up set of attributes by specify the groups you want included To get an idea of what attributes are in what group, run the command: Get-CoreComputerAttributes -PrintAttributes This will print all the groups to the screen to find the one you need The default group of attributes will always be returned and cannot be changed You can specify additional attributes using the custom attribute param. Use the printattribute command to see the syntax The reason we return a hash table is so we can get the Core API to return friendly names so we do not have to process stuff For example this entry: @{"usage_type"="usage_type.name"} Typically the Core API would return a usage_type Class, so by using dot notation we have Core expand it to return the name. By using a hashtable in this fashion, the "friendly" name is the key and the actual Core query is the value ------------ DEV NOTES: ------------- If you are adding or removing an attribute group, you must make sure you: - Update the ValidateSet for attributes on Find-CoreComputer - Update the ValidateSet for attributes on this function - Update the array for attributes in the $PrintAttributes if statement at the bottom of this function If you are adding an attribute group, you MUST make sure the hashtable variable you create matches this naming convention: $TicketAttributes so for example, Network would be $NetworkTicketAttributes. This is the same name used in the ValidateSet. if you name the variable differently it will not be picked up by the loop in the PrintAttributes section so will not be written to screen .PARAMETER Attributes Optional Array of additional groups of attribute to return This would typically be passed from Find-CoreComputer You can specify any combination of attribute groups you want, depending on your requirements Returning every group is obviously going to slow down a core query, so try to keep the groups to a minimum The groups "Skus" is actually subattributes, which will be even slower, so avoid using this unless you absolutly have too To see a list of what attributes are in what group, use Get-CoreComputerAttributes -PrintAttributes .PARAMETER PrintAttributes Can only be used by itself Run to get a print out of all the attribute groups and their PoshCore name, Core API value and the Custom attribute syntax Example output of default values for computer (note, values subject to change) Attribute group name: Default ---------------------------------------------------------------------------------------------------------------------------------------------------------- | PoshCore name: | Core API value: | Custom attribute syntax: | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | account_id | account.number | @{"account_id"="account.number"} | | name | name | @{"name"="name"} | | account_name | account.name | @{"account_name"="account.name"} | | nickname | nickname | @{"nickname"="nickname"} | | datacenter_symbol | datacenter.symbol | @{"datacenter_symbol"="datacenter.symbol"} | | status_name | status.name | @{"status_name"="status.name"} | | number | number | @{"number"="number"} | ---------------------------------------------------------------------------------------------------------------------------------------------------------- .EXAMPLE Prints out of all the attribute groups and their PoshCore name, Core API value and the Custom attribute syntax Get-CoreComputerAttributes -PrintAttributes .EXAMPLE Get a hashtable of the default computer attributes. This should then be passed to Get-CoreWhereWrapper attribute param $Attributes = Get-CoreComputerAttributes .EXAMPLE Get a hashtable of the default, Network and Implementation related attributes. This should then be passed to Get-CoreWhereWrapper attribute param $Attributes = Get-CoreComputerAttributes -Attributes Network,Implementation output hashtable: Name Value ---- ----- vcc vcc admin_ip_network admin_ip_network created created number number billing_notes billing_notes date_online date_online contract contract.id nickname nickname primary_dns primary_dns datacenter_symbol datacenter.symbol admin_ip admin_ip account_name account.name ip_addresses ip_addresses has_clones has_clones date_contract_received date_contract_received pre_build_message pre_build_message customer_aggexnet_vlans customer_aggexnet_vlans is_ice_complete is_ice_complete primary_ip primary_ip status_name status.name account_id account.number due_to_support_date due_to_support_date complex_managed_vlans complex_managed_vlans aggexnet_vlans aggexnet_vlans exnet_zone exnet_zone.name has_been_online has_been_online comments comments due_date due_date name name .EXAMPLE Get a hashtable of the default, Skus and Domain related attributes. This should then be passed to Get-CoreWhereWrapper attribute param $Attributes = Get-CoreComputerAttributes -Attributes Domain,Skus Note that because skus are subattributes, the value is another hashtable output hashtable: Name Value ---- ----- status_name status.name number number domain_name account_domain_info.domain_name name name add_userid_to_domain account_domain_info.add_userid_to_domain is_add_db_admin_local_admin is_add_db_admin_local_admin datacenter_symbol datacenter.symbol has_default_account_level_d... has_default_account_level_domain is_add_cust_admin_local_admin is_add_cust_admin_local_admin Skus {subattributes, attribute} account_id account.number nickname nickname account_name account.name is_workgroup account_domain_info.is_workgroup .OUTPUTS Hashtable of attributes to use with Invoke-CoreQueryWrapper .NOTES Written by Martin Howlett #> [CmdletBinding(DefaultParameterSetName='Attributes')] Param ( [Parameter(ParameterSetName="Attributes")] [Validateset("Default","Network","Drac","Bandwidth","Attached","Backup","Storage","Misc","Domain","Implementation","Is","Os","Password","Skus","StatusLogs")] [String[]]$Attributes = "Default", [Parameter(ParameterSetName="PrintAttributes")] [Switch]$PrintAttributes ) Begin { Write-Verbose "Start of $($MyInvocation.MyCommand)" } Process { #The default list of params we will always return [Hashtable]$DefaultComputerAttributes = @{ "name" = "name" "account_name" = "account.name" "account_id" = "account.number" "datacenter_symbol" = "datacenter.symbol" "nickname" = "nickname" "number" = "number" "status_name" = "status.name" } [Hashtable]$NetworkComputerAttributes = @{ "admin_ip" = "admin_ip" "admin_ip_network" = "admin_ip_network" "aggexnet_vlans" = "aggexnet_vlans" "complex_managed_vlans" = "complex_managed_vlans" "customer_aggexnet_vlans" = "customer_aggexnet_vlans" "exnet_zone" = "exnet_zone.name" "ip_addresses" = "ip_addresses" "primary_dns" = "primary_dns" "primary_ip" = "primary_ip" "vcc" = "vcc" #"vm_info" = "vm_info" - very slow to respond "Get the VM info of this computer at its VCC" #returns another class #"gateway" = "gateway" } [Hashtable]$DracComputerAttributes = @{ "drac_usernames" = "drac_passwords.username" "drac_passwords" = "drac_passwords.password" "drac_ips" = "dracnet_ips.ip_address" "has_drac" = "has_dracnet" } [Hashtable]$BandwidthComputerAttributes = @{ "bandwidth_data" = "bandwidth_data" "bw_poller" = "bw_poller" "bw_subscription" = "bw_subscription" } [Hashtable]$AttachedComputerAttributes = @{ "attached_devices" = "attached_devices.number" "attached_firewalls" = "attached_firewalls.number" "attached_san_or_das" = "attached_san_or_das.number" "attached_usb_server_link" = "attached_usb_server_link.number" } [Hashtable]$BackupComputerAttributes = @{ "backupnet_ip" = "backupnet_ip" "backupnet_ips" = "backupnet_ips" "backupnet_netmask" = "backupnet_netmask" "current_active_bkhost" = "current_active_bkhost" "cvuser_password" = "cvuser_password" "is_managed_backup" = "is_managed_backup" "mb_password" = "mb_password" "mbu_oosbp" = "mbu_oosbp" #Returns another class #"bkhost" = "bkhost" #returns part #"mbu_retention" = "mbu_retention" #"mbu_schedule" = "mbu_schedule" } [Hashtable]$StorageComputerAttributes = @{ "cluster_source_dsan" = "cluster_source_dsan" "das_iscsi_config_list" = "das_iscsi_config_list" "cluster_target_dsan" = "cluster_target_dsan" "dedicated_san_list" = "dedicated_san_list" "dnas_storage_info" = "dnas_storage_info" "disk_groups" = "disk_groups" "host_iscsi_config_list" = "host_iscsi_config_list" "hot_spare_list" = "hot_spare_list" "shared_storage" = "shared_storage" "shared_storage_hosts" = "shared_storage_hosts" } [Hashtable]$MiscComputerAttributes = @{ "emergency_instructions" = "emergency_instructions" "device_in_cluster" = "device_in_cluster" "am_queue" = "am_queue.name" "location" = "location" "scheduled_cancellation_date" = "scheduled_cancellation_date" "scheduled_cancellation_reason" = "scheduled_cancellation_reason" "segment" = "segment.name" "segment_queue" = "segment_queue.name" "service_level_name" = "service_level_name" "support_level" = "support_level" #Added for testing #"status_group" = "status.groups" #This returns every ticket the device has been on #"tickets" = "tickets.number" } [Hashtable]$DomainComputerAttributes = @{ "has_default_account_level_domain" = "has_default_account_level_domain" "is_add_cust_admin_local_admin" = "is_add_cust_admin_local_admin" "is_add_db_admin_local_admin" = "is_add_db_admin_local_admin" "domain_name" = "account_domain_info.domain_name" "add_userid_to_domain" = "account_domain_info.add_userid_to_domain" "is_workgroup" = "account_domain_info.is_workgroup" } [Hashtable]$ImplementationComputerAttributes = @{ "billing_notes" = "billing_notes" "comments" = "comments" "created" = "created" "contract" = "contract.id" "date_online" = "date_online" "date_contract_received" = "date_contract_received" "due_date" = "due_date" "due_to_support_date" = "due_to_support_date" "has_been_online" = "has_been_online" "has_clones" = "has_clones" "is_ice_complete" = "is_ice_complete" "pre_build_message" = "pre_build_message" } [Hashtable]$IsComputerAttributes = @{ "is_behind_net_device" = "is_behind_net_device" "is_cisco_asa_juniper_srx" = "is_cisco_asa_juniper_srx" "is_cluster" = "is_cluster" "is_firewall" = "is_firewall" "is_hypervisor" = "is_hypervisor" "is_linux" = "is_linux" "is_loadbalancer" = "is_loadbalancer" "is_online" = "is_online" "is_red_hat_enterprise" = "is_red_hat_enterprise" "is_register_nic_dns" = "is_register_nic_dns" "is_server" = "is_server" "is_source_or_target_vm" = "is_source_or_target_vm" "is_uk_account" = "is_uk_account" "is_virtual" = "is_virtual" "is_virtual_machine" = "is_virtual_machine" "is_windows" = "is_windows" } [Hashtable]$OsComputerAttributes = @{ "platform_name" = "platform_name" "platform_type" = "platform_type" "platform_model" = "platform_model" "platform_instructions" = "platform_instructions" "os_name" = "os_name" "os" = "os" "os_type" = "os_type" "type" = "type" "usage_type" = "usage_type.name" } #additional attributes for passwords [Hashtable]$PasswordComputerAttributes = @{ "admin_password" = "root_password" "rack_password" = "rack_password" "rack_opt_out" = "opt_out" "rack_rotation_cycle_number" = "password_rotation_cycle_number" "primary_userid" = "primary_userid" "primary_userid_password" = "primary_userid_password" "rba_login_method" = "rba_login_method.name" "rba_login_user" = "rba_login_user" "rba_login_user_password" = "rba_login_user_password" "webmin_password" = "webmin_password" } #status logs subattributes [Hashtable]$StatusLogsSubAttributes = @{ "StatusLogs" = @{ "id"="id" "attribute"="status_logs" "subattributes" = @{ "computer_number" = "computer.number" "new_status" = "new_status.name" "old_status" = "old_status.name" "timestamp" = "timestamp" } } } #Sku subattributes $SkuComputerSubattributes = @{ Skus = @{ "attribute" = "parts"; "subattributes" = @{ "Description" = "ctk_product.description"; "sku" = "sku_number"; "label" = "display_label"; "modified"= "modified"; "part_attributes"= @{ "attribute" = "partributes"; "subattributes" = @( "value", "sku_attribute.description" ) } } } } #Create output object [Hashtable]$ComputerAttributes = @{} $ComputerAttributes += $DefaultComputerAttributes Write-Verbose "adding Default attributes" #Add our top level attributes Switch ($Attributes) { {$_ -contains 'Network'}{$ComputerAttributes += $NetworkComputerAttributes ; Write-Verbose "adding Network attributes"} {$_ -contains 'Drac'}{$ComputerAttributes += $DracComputerAttributes ; Write-Verbose "adding Drac attributes"} {$_ -contains 'Bandwidth'}{$ComputerAttributes += $BandwidthComputerAttributes ; Write-Verbose "adding Bandwidth attributes"} {$_ -contains 'Attached'}{$ComputerAttributes += $AttachedComputerAttributes ; Write-Verbose "adding Attached attributes"} {$_ -contains 'Backup'}{$ComputerAttributes += $BackupComputerAttributes ; Write-Verbose "adding Backup attributes"} {$_ -contains 'Storage'}{$ComputerAttributes += $StorageComputerAttributes ; Write-Verbose "adding Storage attributes"} {$_ -contains 'Misc'}{$ComputerAttributes += $MiscComputerAttributes ; Write-Verbose "adding Misc attributes"} {$_ -contains 'Domain'}{$ComputerAttributes += $DomainComputerAttributes ; Write-Verbose "adding Domain attributes"} {$_ -contains 'Implementation'}{$ComputerAttributes += $ImplementationComputerAttributes ; Write-Verbose "adding Implementation attributes"} {$_ -contains 'Os'}{$ComputerAttributes += $OsComputerAttributes ; Write-Verbose "adding Os attributes"} {$_ -contains 'Is'}{$ComputerAttributes += $IsComputerAttributes ; Write-Verbose "adding Is attributes"} {$_ -contains 'Password'}{$ComputerAttributes += $PasswordComputerAttributes ; Write-Verbose "adding Password attributes"} {$_ -contains 'Skus'}{$ComputerAttributes += $SkuComputerSubattributes ; Write-Verbose "adding Skus attributes"} {$_ -contains 'StatusLogs'}{$ComputerAttributes += $StatusLogsSubAttributes ; Write-Verbose "adding Status Log SubAttributes"} } #if user selected the print attribute switch we just print them to screen and dont return anything if($PrintAttributes) { Write-Verbose "PrintAttributes selected" #set variables to generate our hash table for Write-AttributesToHost #$AllGroups should match the ValidateSet on the Attributes param on this function $AttributeClass = "Computer" #i intentially left out SKUs as i didnt know how to present this nicely. its a bit of a outlier $AllGroups = @("Default","Network","Drac","Bandwidth","Attached","Backup","Storage","Misc","Domain","Implementation","Is","Os","Password","StatusLogs") #create the hashtable of all attribute hashtable groups we pass to Write-Attributes $AttributeHashtable = @{} ForEach ($Group in $AllGroups) { $AttributeHashtable.Add($Group,$((Get-Variable -Name "$Group$AttributeClass`Attributes").Value)) } Write-AttributesToHost -AttributeHashtable $AttributeHashtable } else { Return $ComputerAttributes } } End { #Log to appstats Set-LogtoAppstats -FunctionID "Get-CoreComputerAttributes" -AppID "PoshCore" Write-Verbose "End of $($MyInvocation.MyCommand)" } } #endregion #################### ComputerWhere functions - END ##################### #################### Computer method wrapper functions - BEGIN #################### #region Function Get-CoreComputerStatusTransitions { <# .SYNOPSIS Gets the valid transition statuses of a computer .DESCRIPTION Gets the valid transition statuses of a computer Both downgrade and upgrade statuses See list of statuses here: https://ws.core.rackspace.com/ctkapi/browse/Computer/Status .PARAMETER Computers Mandatory Array of integers Computer numbers of the devices to get the status of If you want a single computer, just pass the single computer number .EXAMPLE Get the computer status trasusions for 2 devices Set-CoreComputerStatusTransitions -Computers 560559,560570 .NOTES Written by Martin Howlett #> Param ( [Parameter(Mandatory=$true)] [ValidatePattern("^[0-9]{6}$")] [ValidateCount(1,249)] [ValidateNotNullOrEmpty()] [Int[]]$Computers ) Begin { Write-Verbose "Start of $($MyInvocation.MyCommand)" } Process { #Update the input array to remove any duplicate values, which will save time during execution $Computers = Get-UniqueArray -InputArray $Computers #get all our computers and their current status plus possible transitions $StatuseAttributes = @{ downgrade_states = 'downgrade_states' ; upgrade_states = 'upgrade_states' } Try { $AllComputers = Find-CoreComputer -Computers $Computers -CustomAttributes $StatuseAttributes } catch { $Reason = "$($MyInvocation.MyCommand) - Failed to get Core computers $($Computers -join ',')" $Params = @{ FunctionName = "$($MyInvocation.MyCommand)" CallingScript = "$($MyInvocation.ScriptName)" Line = "$($_.invocationInfo.ScriptLineNumber)" ErrorMsg = "$($_.exception.message)" CommandName = "$($_.exception.CommandName)" Variables = $(Get-Variable -Scope Local -ErrorAction SilentlyContinue) Version = "$Version" Reason = "$Reason" } Export-PowershellError @Params Throw "$Reason" } Return $AllComputers } End { #Log to Appstats Set-LogtoAppstats -FunctionID "Set-CoreComputerStatus" -AppID "PoshCore" Write-Verbose "End of $($MyInvocation.MyCommand)" } } Function Set-CoreComputerStatus { <# .SYNOPSIS Sets the status of a Core computer .DESCRIPTION Uses the CTKAPI 'changeStatus' method to set computer status See list of statuses here: https://ws.core.rackspace.com/ctkapi/browse/Computer/Status Note that some status changes are not valid so can fail. You can use Get-CoreComputerStatusTransitions to validate before (although this function will validate them anyway) .PARAMETER Computers Mandatory Array of integers Computer numbers of the devices to set the status of If you want a single computer, just pass the single computer number .PARAMETER Status Mandatory Example: Online/Computer Description: The name of the status to change the computer to See list here: https://ws.core.rackspace.com/ctkapi/browse/Computer/Status Not all transitions are valid but the function will validate it .PARAMETER Reason Mandatory String Example: Ready for customer Description: The reason you are changing the device status .PARAMETER ContractID Optional int Example: 258357 Description: THe contract ID (some new devices need this to mark them online) .EXAMPLE Set the computer status on a single device Set-CoreComputerStatus -Computers 560559 -Status 'Online/Complete' -Reason "Device is ready for customer" .EXAMPLE Set the computer status on an array of devices Set-CoreComputerStatus -Computers @(560559,560570,502664) -Status 'Online/Complete' -Reason "Device is ready for customer" .EXAMPLE Set the computer status on a single device with a contract ID Set-CoreComputerStatus -Computers 560559 -Status 'Support Maintenance' -Reason "Test" -ContractId 1593574 .OUTPUTS True or false .NOTES Written by Martin Howlett Based on original function by Bob Larkin in Ctkcore Used structure from Add-CoreTicketComputer by Dimitar Filipov #> Param ( [Parameter(Mandatory=$true)] [ValidatePattern("^[0-9]{6}$")] [ValidateCount(1,249)] [ValidateNotNullOrEmpty()] [Int[]]$Computers, [Parameter(Mandatory=$true)] [Validateset( "Computer No Longer Active", "Order Submitted", "Sent Contract", "Received Contract", "In Assembly", "Ready for QC", "QC Complete/Ready to Rack", "Segment Configuration", "Ready for Account Team", "Online/Complete", "Under Repair", "Hardware Upgrade", "Migration Server", "Suspended - AUP Violation", "Suspended - Billing", "Suspended - Project", "Suspended - VM", "Wait Suspension - Billing", "Wait Suspension - Project", "Wait Suspension - VM", "Reactivation", "Compromised: System/Root Level", "Compromised: Application/User Level", "Wait Suspension - AUP", "Decommission", "Rekick", "Racked and Ready", "Waiting On Parts", "Sent to Production", "Racked", "Waiting On Configuration Implementation", "Waiting On Cabinet Provisioning", "Waiting On IPs", "Waiting On Migration", "Waiting On Other", "Support Maintenance", "Online - Pending Net Device", "Sent to Customer", "Racked - Need IPs", "Racked - Waiting Remote QC", "Implementation Document Received", "Deployment Complete", "Replication Test", "KIR: Automation", "KIR: Racked", "KIR: Discovery", "KIR: Kick In Progress", "KIR: Kick Complete", "Suspended VM-Replication", "Suspended VM-Failed Over" )] [String]$Status, [Parameter(Mandatory=$true)] [String]$Reason, [Parameter()] [ValidatePattern("^\d{1,99}$")] [int]$ContractID ) Begin { Write-Verbose "Start of $($MyInvocation.MyCommand)" } Process { #Convert the status friendly name to the status id Switch ($Status) { "Computer No Longer Active" {$StatusId = -1} "Order Submitted" {$StatusId = 1} "Sent Contract" {$StatusId = 2} "Received Contract" {$StatusId = 3} "In Assembly" {$StatusId = 4} "Ready for QC" {$StatusId = 5} "QC Complete/Ready to Rack" {$StatusId = 6} "Segment Configuration" {$StatusId = 9} "Ready for Account Team" {$StatusId = 10} "Online/Complete" {$StatusId = 12} "Under Repair" {$StatusId = 13} "Hardware Upgrade" {$StatusId = 14} "Migration Server" {$StatusId = 15} "Suspended - AUP Violation" {$StatusId = 16} "Suspended - Billing" {$StatusId = 17} "Suspended - Project" {$StatusId = 18} "Suspended - VM" {$StatusId = 19} "Wait Suspension - Billing" {$StatusId = 31} "Wait Suspension - Project" {$StatusId = 32} "Wait Suspension - VM" {$StatusId = 33} "Reactivation" {$StatusId = 40} "Compromised: System/Root Level" {$StatusId = 42} "Compromised: Application/User Level" {$StatusId = 44} "Wait Suspension - AUP" {$StatusId = 45} "Decommission" {$StatusId = 50} "Rekick" {$StatusId = 51} "Racked and Ready" {$StatusId = 60} "Waiting On Parts" {$StatusId = 62} "Sent to Production" {$StatusId = 63} "Racked" {$StatusId = 64} "Waiting On Configuration Implementation" {$StatusId = 65} "Waiting On Cabinet Provisioning" {$StatusId = 66} "Waiting On IPs" {$StatusId = 67} "Waiting On Migration" {$StatusId = 68} "Waiting On Other" {$StatusId = 69} "Support Maintenance" {$StatusId = 70} "Online - Pending Net Device" {$StatusId = 71} "Sent to Customer" {$StatusId = 72} "Racked - Need IPs" {$StatusId = 73} "Racked - Waiting Remote QC" {$StatusId = 185} "Implementation Document Received" {$StatusId = 186} "Deployment Complete" {$StatusId = 187} "Replication Test" {$StatusId = 188} "KIR: Automation" {$StatusId = 189} "KIR: Racked" {$StatusId = 190} "KIR: Discovery" {$StatusId = 191} "KIR: Kick In Progress" {$StatusId = 192} "KIR: Kick Complete" {$StatusId = 193} "Suspended VM-Replication" {$StatusId = 194} "Suspended VM-Failed Over" {$StatusId = 195} } Try { #Get our valid transitions $AllComputers = Get-CoreComputerStatusTransitions -Computers $Computers } catch { $Reason = "$($MyInvocation.MyCommand) - Failed to get Core computer transitions $($Computers -join ',')" $Params = @{ FunctionName = "$($MyInvocation.MyCommand)" CallingScript = "$($MyInvocation.ScriptName)" Line = "$($_.invocationInfo.ScriptLineNumber)" ErrorMsg = "$($_.exception.message)" CommandName = "$($_.exception.CommandName)" Variables = $(Get-Variable -Scope Local -ErrorAction SilentlyContinue) Version = "$Version" Reason = "$Reason" } Export-PowershellError @Params Throw "$Reason" } #array to store all devices that have been successfully (or unsuccessfully) had their status changed $Output = @() foreach ($Computer in $Computers) { #Match the current computer with the list we got from core $CurrentComputer = $null $CurrentComputer = $AllComputers | Where-object {$_.Number -eq $Computer} if(-not $CurrentComputer.number) { $Reason = "Poshcore - Set-CoreComputerStatus - Failed to match computer $Computer to returned Core results" $Params = @{ FunctionName = "$($MyInvocation.MyCommand)" CallingScript = "$($MyInvocation.ScriptName)" Line = "$($_.invocationInfo.ScriptLineNumber)" ErrorMsg = "$($_.exception.message)" CommandName = "$($_.exception.CommandName)" Variables = $(Get-Variable -Scope Local -ErrorAction SilentlyContinue) Version = "$Version" Reason = "$Reason" } Export-PowershellError @Params Throw "$Reason" } #Validate device is already not in this state If($Status -eq $CurrentComputer.status_name) { $Output += New-Object PSObject -Property @{ Computer = $Computer Result = $True Detail = "Computer is already in $Status"; } Write-Verbose "Computer $computer is already in status $Status" } else { #Validate this is a legal transition If(($CurrentComputer.downgrade_states.name -notcontains $Status) -and ($CurrentComputer.upgrade_states.name -notcontains $Status)) { $Output += New-Object PSObject -Property @{ Computer = $Computer Result = $False Detail = "$Status is not a valid transition"; } Write-Verbose "Failed to updated computer $computer status to $Status as it is not a valid transition" Write-Verbose "Valid transitions: Downgrade: $($CurrentComputer.downgrade_states.name -join ' | ')" Write-Verbose "Valid transitions: Upgrade: $($CurrentComputer.upgrade_states.name -join ' | ')" } else { #try and update status Try { #if we have a contract ID we cannot use the API and go via the website #this will avoid issues with permissions and the API If($ContractID) { Write-Verbose "Computer $($CurrentComputer.number) has a contract ID so attempting to set via WebRequestSession" if(-not $Session) { Write-Verbose "Creating new Core session variable" $session = New-Object Microsoft.PowerShell.Commands.WebRequestSession $cookie = New-Object System.Net.Cookie $cookie.Name = "rackspace_admin_session" $cookie.Value = "$(Get-PoshCoreToken -AsPlainText)" $cookie.Domain = "core.rackspace.com" $session.Cookies.Add($cookie); } $URL = "https://core.rackspace.com/py/account/upgradeContractWithSelectStatus.pt" $params = @{ "$($CurrentComputer.Number)" = "$StatusId" "contract_id" = "$ContractID" "account_number" = "$($CurrentComputer.account_id)" } Write-Verbose "Curent computer number: $($CurrentComputer.Number)" Write-Verbose "StatusId : $StatusId" Write-Verbose "ContractID : $ContractID" Write-Verbose "account_number : $($CurrentComputer.account_id)" $Result = Invoke-WebRequest $url -WebSession $session -Body $params -ErrorAction Stop -Method Post <# This is a table in the returning web page that lists devices and their statuses, so we can check success from this Server (Status) Server Type Server Domain Info 912345 (Segment Configuration) change 912345-db1.intensive.int #> #Parse the HTML we get back and get the server table $ResultTable = ($Result.ParsedHtml.getElementById('server_table')) #parse the table for the row with the computer number $ResultTableRow = ($ResultTable.rows | where-object {$_.innertext -like "*$computer*"}).InnerText Write-Verbose "$Computer : returned HTML table row" Write-Verbose "$ResultTableRow" #Check if the row with the server references Ready for Account Team if($ResultTableRow -like "*(Ready for Account Team)*") { $ContactIdResult = $true } else { $ContactIdResult = $false } Write-Verbose "ContactIdResult = $ContactIdResult" } else { #Build are params $KeyWordArgs = @{ reason = $Reason new_status = $StatusId } $Result = $Null $Result = Invoke-CoreMethodWrapper -LoadArgument $Computer -KeywordArgs $KeyWordArgs -Method "changeStatus" -Class Computer } } catch { $Reason = "Poshcore - Set-CoreComputerStatus - Failed to set computer $Computer to $Status" $Params = @{ FunctionName = "$($MyInvocation.MyCommand)" CallingScript = "$($MyInvocation.ScriptName)" Line = "$($_.invocationInfo.ScriptLineNumber)" ErrorMsg = "$($_.exception.message)" CommandName = "$($_.exception.CommandName)" Variables = $(Get-Variable -Scope Local -ErrorAction SilentlyContinue) Version = "$Version" Reason = "$Reason" } Export-PowershellError @Params Throw "$Reason" } #return result (when doing it via invoke-webrequest we get a webpage back that references the day if(($Result.success) -or ($ContactIdResult)) { $Output += New-Object PSObject -Property @{ Computer = $Computer Result = $True Detail = "Updated computer to $Status" } Write-Verbose "Successfully updated computer $computer status to $Status" } else { $Output += New-Object PSObject -Property @{ Computer = $Computer Result = $False Detail = "Failed to update to $Status - unknown Core error" } Write-Verbose "Failed to updated computer $computer status to $Status" } } } } Return $Output } End { #Log to Appstats Set-LogtoAppstats -FunctionID "Set-CoreComputerStatus" -AppID "PoshCore" Write-Verbose "End of $($MyInvocation.MyCommand)" } } #endregion #################### Computer method wrapper functions - END #####################