Pull Server names and ip address and see if they're live - list

I am looking to run a PowerShell script that will pull all servers from AD, show me the FQDN and IP address as well as tell me if the server is pinging.
I have a couple of scripts that do certain parts but would like to get something all in one and am having a hard time doing it.
Ping a list of servers:
$ServerName = Get-Content "c:\temp\servers.txt"
foreach ($Server in $ServerName) {
if (test-Connection -ComputerName $Server -Count 2 -Quiet ) {
"$Server is Pinging "
} else {
"$Server not pinging"
}
}
I also have a script to pull all servers from AD which shows server name, FQDN, and OS version:
Import-Module ActiveDirectory
Get-ADComputer -Filter {OperatingSystem -like '*Windows Server*'} -Properties * |
select Name, DNSHostName, OperatingSystem
Any help in getting a script to show me all servers in my environment with FQDN, IP address and if there live would be appreciated.

You should only choose desired properties with the -Property argument and not pull everything through network with *. Also quotes should be used with -Filter, not braces.
You can add a calculated property to Select-Object and get the value from Test-NetConnection:
Get-ADComputer -Filter "OperatingSystem -like '*Windows Server*'" -Properties dnshostname, operatingsystem |
Select-Object name, dnshostname, operatingsystem, `
#{n="PingSucceeded";e={(Test-NetConnection $_.name).PingSucceeded}}

Related

powercli site recovery manager: determine which protection group an unprotected VM will be in. SRM uses array based replication

I use automation to deply VM's to various vcenter clusters.
I then confgiure SRM network mapping to create a network map between the cluster that the VM is in and the cluster which is used for DR purposes, in the protection group for those two clusters.
SRM is set up for array based replication, so as long as the VM is placed on replicated storage in the right cluster it will appear in SRM under the protection group, if a network mapping is in place then the VM will be auto protected by SRM or via my SRM config script.
I currently have the primary cluster, DR cluster and protection group hard coded, but would like to determine the protection group a VM is in and the name of the two clusters which the protection group is set up for, that way any changes to cluster configuration is automatically picked up and doesn't require manual changes to the SRM config script.
I've looked in the SRM API docs but it's not something I have worked out yet!
I have solved the issue:
$credential = Get-Credential
$server_name = "test-server"
Connect-VIServer -Server $primaryDC -Credential $credential
$srmConnection = Connect-SrmServer -Credential $credential -RemoteCredential $credential
Connect-VIServer -Server $secondaryDC -Credential $credential
$srmApi = $srmConnection.ExtensionData
$protectionGroups = $srmApi.Protection.ListProtectionGroups()
foreach ($protectionGroup in $protectionGroups){
$associatedVms = $protectionGroup.ListProtectedDatastores() | Get-VIObjectByVIView | Get-VM | Where-Object {($_.name -eq $server_name) -and($_.ExtensionData.Config.ManagedBy.ExtensionKey -ne 'com.vmware.vcDr' )}
foreach ($vm in $associatedVms) {
if ($vm.Name -eq $server_name) {
$protection_group_name = $protectionGroup.GetInfo().Name
$primary_cluster = get-vm -name $server_name | get-cluster
$primary_cluster_res_group = $primary_cluster.ExtensionData.ResourcePool
$srm_resource_groups = $srmApi.inventoryMapping.getResourcePoolMappings()
foreach ($resource_group in $srm_resource_groups){
if ($resource_group.PrimaryObject -eq $primary_cluster_res_group){
$secondary_res_group = $resource_group.SecondaryObject
}
}
}
}
}
$secondary_cluster = Get-Cluster | Where-Object {$_.ExtensionData.ResourcePool -eq $secondary_res_group}
Write-Host "VM: $vm - Protection Group: $protection_group_name - Primary cluster: $primary_cluster - Secondary cluster: $secondary_cluster - Primary ResGrp: $primary_cluster_res_group - Secondary ResGrp: $secondary_res_group"

Rename ec2 hostname using userdata does not work

I am trying to rename the hostname to a specific one - TEAM-CNTNR using the user-data script but after the EC2 instance comes up online and I connect to it (via Session Manager), the hostname is the random one that EC2 service gives the instance such as EC2AMAZ-VHAGRNV.
This is my user-data script, am I missing something? This is my user-data script:
<powershell>
Import-Module ECSTools
[Environment]::SetEnvironmentVariable("ECS_ENABLE_AWSLOGS_EXECUTIONROLE_OVERRIDE", $TRUE, "Machine")
Initialize-ECSAgent -Cluster "${cluster_name}" -EnableTaskIAMRole -LoggingDrivers '["json-file","awslogs"]' -EnableTaskENI
# rename the instance hostname so that it works with the gMSA account
Rename-Computer -NewName "TEAM-CNTNR" -Force
## instance-domain-join code here. Omitted for brevity
# Perform the domain join
Add-Computer -DomainName "$domain_name.$domain_tld" -OUPath "OU=Computers,OU=enrcloud,DC=enr,DC=cloud" -ComputerName "$hostname" -Credential $credential -Passthru -Verbose -Restart
</powershell>
<runAsLocalSystem>true</runAsLocalSystem>
It was revealed to me that there is a NewName parameter that can be used that is part of the Add-Computer command that would:
join the machine to the new domain
and change its name at the same time
Add-Computer ... -NewName "MyComputer" ...
Reference: Microsoft site

Powershell script to get only Hour and Minute from NET TIME command

I am trying to retrieve only the Date and Time from the PowerShell script, Below is what I have tried till now:
Script:
NET TIME \\ComputerName | Out-File $location
(Get-Content $location) | % {
if ($_ -match "2018 : (.*)") {
$name = $matches[1]
echo $name
}
}
net time output is as below:
Current time at \\Computer Name is 1/3/2018 1:05:51 PM
Local time (GMT-07:00) at \\Computer Name is 1/3/2018 11:05:51 AM
The command completed successfully.
I only need the part in local time "11:05".
Although Get-Date doesn't support querying remote computers, the date/time and timezone information from a remote computer can be retrieved using WMI; an example can be found at this TechNet PowerShell Gallery page. Using the Win32_LocalTime class, adjusted based on the Win32_TimeZone class, will provide the information in a form that is easily converted into a [DateTime] for further use in your script.
Use -match to test a regex
Then check the matches with autogenerated $matches array
PS> "Current time at \Computer Name is 1/3/2018 1:05:51 PM Local time (GMT-07:00) at \Computer Name is 1/3/2018 11:05:51 AM" -match '(\d\d:\d\d):'
True
PS> $matches
Name Value
---- -----
1 11:05
0 11:05:
PS> $matches[1]
11:05
Brief
You can use this function to get whatever information you want. I adapted the code from this script. It converts the LocalDateTime value obtained using Get-WmiObject into a DateTime object. You can do whatever you want with the date information thereafter. You can also adapt this to use whichever DateTime variable you want (i.e. last boot time).
Code
function Get-RemoteDate {
[CmdletBinding()]
param(
[Parameter(
Mandatory=$True,
ValueFromPipeLine=$True,
ValueFromPipeLineByPropertyName=$True,
HelpMessage="ComputerName or IP Address to query via WMI"
)]
[string[]]$ComputerName
)
foreach($computer in $ComputerName) {
$timeZone=Get-WmiObject -Class win32_timezone -ComputerName $computer
$localTime=([wmi]"").ConvertToDateTime((Get-WmiObject -Class Win32_OperatingSystem -ComputerName $computer).LocalDateTime)
$output=[pscustomobject][ordered]#{
'ComputerName'=$computer;
'TimeZone'=$timeZone.Caption;
'Year'=$localTime.Year;
'Month'=$localTime.Month;
'Day'=$localTime.Day;
'Hour'=$localTime.Hour;
'Minute'=$localTime.Minute;
'Seconds'=$localTime.Second;
}
Write-Output $output
}
}
Call the function using either of the following methods. The first is for a single computer and the second for multiple computers.
Get-RemoteDate "ComputerName"
Get-RemoteDate #("ComputerName1", "ComputerName2")
I realize this may not work for you if you do not have PowerShell remoting enabled, but if it is I would do it this way.
Invoke-Command -ComputerName ComputerName -ScriptBlock {(Get-Date).ToShortTimeString()}

Connecting Mulitple VCenter Servers and collect information with Powercli

I have a list of VCenter servers. They are on different locations and of different customers. I have created a text file with all the vcenter servers and credentials like below..I have more than 20 Vcenter Servers. I need to collect information of VM, Datastores, etc.(for which I have scripts).
Connect-VIServer vcenter0001 -User vcenter0001\sysdep -Password "Passwowrd1"
Connect-VIServer vcenter0002 -User vcenter0002\sysdep -Password "Passwowrd2"
I want to connect to each VCenter server and execute my scripts. Please help me. Thanks in Advance.
There's a couple ways to accomplish this, first you need to make sure that your configuration is set to allow for multiple connections. This is done with the following:
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple
Note: It may also be necessary to run the following to enforce the change against all session scopes:
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Scope User
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Scope Session
Afterwards, you can pass multiple vCenter server names in string format or array format to the Connect-VIServer cmdlet to the 'Server' parameter.
Example using strings:
Connect-VIServer -Server vcenter0001,vcenter0002,vcenter0003 -User sysdep -Password "Password"
Example using an array:
$vCenterNames = #('vcenter0001','vcenter0002','vcenter0003')
Connect-VIServer -Server $vCenterNames -User sysdep -Password "Password"
Lastly, since it looks like you may be using local accounts instead of a single domain account, you could look at integrating the VICredentialStore. This saves your credentials in an XML file that will be referenced automatically at time of authentication.
Example Usage:
New-VICredentialStoreItem -Host vcenter0001 -User vcenter0001\sysdep -Password "Password"
New-VICredentialStoreItem -Host vcenter0002 -User vcenter0002\sysdep -Password "Password"
New-VICredentialStoreItem -Host vcenter0003 -User vcenter0003\sysdep -Password "Password"
Connect-VIServer -Server vcenter0001,vcenter0002,vcenter0003
Suppose you have a top secret csv file where you store the connection info (i.e. vi server fqdn, logon user name and passwords) that looked like this:
viserver, username, password
myfav.cust1.org, cust1usr, cust1pw
my2fav.cust2.net, cust2usr, cust2pw
myleastfav.cust3.com, cust3usr, cust3pw
and it was saved in: c:\mysecretdocs\custviservers.csv
you could use import-csv and a foreach statement to do your inventory dirty work with a function that looked something like this:
function get-vminventory
{
$viCntinfo = Import-Csv c:\mysecretdocs\custviservers.csv
foreach ($vi in $viCntInfo)
{
$convi = connect-viserver -server $vi.viserver -username $vi.username -password $vi.password
$vms = get-vm
$vms | select name, MemoryGB, NumCpu,
#{ n = "hostname"; e = { $_.guest.hostname } },
#{ n = "ip"; e = { $_.guest.ipaddress -join ", " } },
#{ n = "viserver"; e = { $convi.Name } }
$discvi = disconnect-viserver -server * -force -confirm:$false
}
}
You can run any of the PowerCLI inventory or custom commands there and select whatever output you want, that's just an example using Get-VM. Either dot source the function or just paste it into your shell. Then execute it and put the output in a csv like this:
get-vminventory | Export-Csv c:\mycustomerdata\vminfo.csv

Uninstall program on several servers

I have a bunch of servers I have to uninstall an app from. I am using:
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match "application name"
}
$app.Uninstall()
I have tested the above out and it works great. I want to now run this so it uninstalls the app on a bunch of servers. I know I can use the for each option but for some reason I am having an issue getting it to work.
I created a text file called servers and listed my servers in there but it errors out each time.
Does anyone have a good pay to add a for each part to my above uninstall portion so it works?
The -ComputerName parameter of Get-WmiObject accepts a list of computernames.
$servers = Get-Content 'C:\your\computerlist.txt'
Get-WmiObject -Computer $servers -Class Win32_Product |
? { $_.Name -like '*application name*' } |
% { $_.Uninstall() }
Later on the page that you got your original code from, there is an answer from David Setler that does what you need. Slightly modified to fir your scenario:
$computers = Get-Content C:\servers.txt
foreach($server in $computers){
$app = Get-WmiObject -Class Win32_Product -computer $server | Where-Object {
$_.Name -match "application name"
}
$app.Uninstall()
}
Assuming $computers is the list of servers from your servers text file.
I would stay away from win32_product because this class isn't working properly.
See https://support.microsoft.com/en-us/kb/974524.
Basicly what happens when you query this class is that every msi will trigger a repair an the software package (spamming the eventlog) which in some cases can screw with installed software (I've seen broken installations of some programs after querying this class - though it's rare, you don't want to risk this on production servers).