Get-View to speed up things using regex

I was playing around with the get-view cmdlet and found something I didn’t know yet.

On the site there is an example

Get-View -ViewType VirtualMachine -Filter @{"Name" = "VM"}

Cool, let’s test that. Hey , why do I get 2 items returned?
I searched for a VM called “Test” and there returned 2 VM’s which are started with “Test”.

I didn’t know that, in the description of the filter object you see:

Specifies a hash of <name>-<value> pairs, where <name> represents the property value to test, and <value> represents a regex pattern the property must match. If more than one pair is present, all the patterns must match.

Ah…

So let’s throw some regex in then:

One way to tighten our patterns is to define a pattern that describes both the start and the end of the line using the special ^ (hat) and $ (dollar sign) metacharacters. Maybe not the best option but it works fine.

To do an exact match on “Test””we use : “^Test$

Now let’s start exact match on Test and do a reset of the VM:

(get-view -ViewType VirtualMachine -Filter @{"name"="^Test$"}).ResetVM()

Cool that works, I’m no regex expert, but the way mentioned above works, because the start..end of the line only exists of VM names.

It would be nicer to use a word boundary so you capture the word only and not the line.

So we can also use \bServername\b:


get-view -ViewType VirtualMachine -Filter @{"name"="\bTest\b"}

Both options work, but may come in handy for the future.

So what I learned, the filter object can be ‘regexed’ !

Logging Function v2.0

As I created an earlier post with a simple logging function in poweshell, a while ago I upgraded this with a specific Error, Success and info switch. This way I can put it with simple colors as output on screen to see if something goes wrong or good. And also logging will be better searchable.

 

$Logfile = "D:\LogFile.txt"

Function LogWrite{
&lt;#
<span style="font-size: 0.95em; line-height: 1.6em;">.SYNOPSIS This functions is used to generate a log file
</span><span style="font-size: 0.95em; line-height: 1.6em;">.DESCRIPTION Function creates output on screen depending on given switch and writes this with error code to the logfile
.PARAMETER $Logstring Location to the logfile
.PARAMETER $Error Switch to identify an error message
.PARAMETER $Success Switch to identify a success message
.PARAMETER $Info Switch to identify an info message
.EXAMPLE PS C:\&gt; Logwrite -error "This is an error"
</span> .INPUTS
System.String,System.Switch
.OUTPUTS
System.String
#&gt;

[CmdletBinding()]
[OutputType([System.String])]
Param(
[string]$Logstring,
[switch]$Error,
[switch]$Success,
[switch]$Info

)
try {
if ($Error){
$logstring = (Get-Date).ToString() + " ERROR: " + $logstring
Write-Host -ForegroundColor red $logstring
}
elseif ($Success){
$logstring = (Get-Date).ToString() + " SUCCESS: " + $logstring
Write-Host -ForegroundColor green $logstring
}
elseif ($Info){
$logstring = (Get-Date).ToString() + " INFO: " + $logstring
Write-Host $logstring
}
else {
$logstring = (Get-Date).ToString() + " INFO: " + $logstring
Write-Host $logstring
}
Add-content $Logfile -value $logstring
}
catch {
throw
}
}

#Example

logwrite -success "Success creating user: $user"
logwrite -error "Error creating user $user"
logwrite -info"Success quering user: $user"

PowerCLI: Show HBA Path Status *Updated*

Because our storage team was doing some upgrades lately they asked if I could the check the storage path status. We have 2 FC HBA’s per server which are connected to a seperate FC switch. Storage normally upgrades 1 path then we check to be sure before starting to upgrade the other path.

Got my inspiration from internet and credits go to them :
https://jfrmilner.wordpress.com/2011/08/27/checking-for-dead-paths-on-hbas-with-powercli/ * Used the output as a starting point where I want to go.
http://practical-admin.com/blog/powercli-show-hba-path-status/
* Pefect clean use of the get-view feature, only nasty part was the end

$result += "{0},{1},{2},{3},{4}" -f $view.Name.Split(".")[0], $hba, $active, $dead, $standby
}
}

ConvertFrom-Csv -Header "VMHost", "HBA", "Active", "Dead", "Standby" -InputObject $result | ft -AutoSize

Which I changed by creating a new object.

$row = "" | Select VMhost,HBA,Active,Dead
$row.VMhost = $view.Name.Split(".")[0]
$row.HBA = $hba
$row.Active = $active
$row.Dead = $dead
$result += $row
}
}
$result|ft -AutoSize

This object then can easily be exported to CSV/Table whatever you like. It also can be easy to for a wrap up like I made at the end.

$result |Measure-Object -Property Active,Dead -Sum|select property,sum|ft -AutoSize

Especially in a larger environment you don’t have to keep scrolling to see where it failed, just look at the summary to see if you need to scroll up 🙂


cls
function Check-DeadPaths{
<#
    .SYNOPSIS
        This function checks and reports path status
    .DESCRIPTION
         This function checks and reports path status
    .PARAMETER Outputfile
        Specify a output file, exported in CSV format.
    .EXAMPLE
        PS C:\> Check-DeadPaths -Outputfile "C:\temp\output.csv"
    .INPUTS
        System.String
    .OUTPUTS
        System.Collections.Hashtable
#>
[CmdletBinding(
    SupportsShouldProcess = $true, ConfirmImpact = "Low")]
    [OutputType([Hashtable])]
	param(
    [Parameter(Mandatory = $false)]
    [string]$Outputfile
	)
    BEGIN {
        try {
        }
        catch {
            Throw
        }
    }
	PROCESS {
        try {
		    if ($pscmdlet.ShouldProcess){
				$views = Get-View -ViewType "HostSystem" -Property Name,Config.StorageDevice
				$result = @()
				foreach ($view in $views | Sort-Object -Property Name) {
					Write-Host "Checking" $view.Name
					$view.Config.StorageDevice.ScsiTopology.Adapter|Where-Object{ $_.Adapter -like "*FibreChannelHba*" } | ForEach-Object{
						$active,$standby,$dead = 0
						$key = $_.Adapter
						$wwn = $view.Config.StorageDevice.HostBusAdapter|Where-Object{$_.key -eq $key}
						$_.Target | ForEach-Object{
							$_.Lun | ForEach-Object{
								$id = $_.ScsiLun
								$multipathInfo = $view.Config.StorageDevice.MultipathInfo.Lun | ?{ $_.Lun -eq $id }
								$active = ([ARRAY]($multipathInfo.Path | ?{ $_.PathState -like "active" })).Count
								$standby = ([ARRAY]($multipathInfo.Path | ?{ $_.PathState -like "standby" })).Count
								$dead = ([ARRAY]($multipathInfo.Path | ?{ $_.PathState -like "dead" })).Count
							}
						}
						$row = "" | Select VMhost,HBA,PortWorldWideName,NodeWorldWideName,Active,Dead
						$row.VMhost = $view.Name.Split(".")[0]
						$row.HBA = $_.Adapter.Split("-")[2]
						$row.PortWorldWideName = "{0:X}" -f $wwn.PortWorldWideName
						$row.NodeWorldWideName = "{0:X}" -f $wwn.NodeWorldWideName
						$row.Active = $active
						$row.Dead = $dead
						$result += $row
					}
				}
            }
		}
        catch {
            [String]$returnMessage = "Failed to create Kibana dashboard for environment $Environment.`r`nScriptname: " + $_.InvocationInfo.ScriptName + "`r`nLine: " + $_.InvocationInfo.ScriptLineNumber + "`r`nError: " + $_.Exception.Message
        }
$result|ft -AutoSize
Write-Host "Total Wrap up:"
$result |Measure-Object -Property Active,Dead -Sum|select property,sum|ft -AutoSize
if ($outputfile){
		$result|Export-Csv $outputfile -Confirm:$false -useculture -NoTypeInformation
	}
 
	END {
        try {
            return @{returnMessage = $returnMessage}
        }
        catch {
            Throw
        }
    }
}

vCenter 6 creating global roles with PowerCLI

While middle in the migration from a vCenter 5.1 environment to a vCenter 6.x environment I wanted to use the Global Roles so I don’t have to set them per vCenter anymore.

So how do I create those global roles?

Well the important thing is to connect to your vCenter (Connect-VIServer) using the administrator@vsphere.local user (or your SSO user if you configured a different one)

Because you login with the SSO user you can create the global roles by just using the New-VIRole command.

Example:
So in with the function below I tried to create a simple function with parameters -From and -To to simply recreate the roles from vCenter1 to vCenter2.
I make use of the logwrite function I posted earlier to spam some messages on screen and to a text file

Before:
– I expect you to be connected to both vCenters using the Connect-VIServer cmdlet.

function Migrate-VIrole{
	<#
		.SYNOPSIS
			Migrates the VCenter roles from one vCenter to another
		.DESCRIPTION
			A detailed description of the function.
		.PARAMETER  $From
			This is the vCenter to read from
		.PARAMETER  $To
			This is the vCenter to build the datacenter on
		.EXAMPLE
			PS C:\> Migrate-VIRole -From vCenter1 -To vCenter2
		.INPUTS
			System.String
		.OUTPUTS
			System.String
	#>
	[CmdletBinding()]
	[OutputType([System.String])]
	param(
		[Parameter(Position=1, Mandatory=$true)]
		[ValidateNotNull()]
		[System.String]
		$From,
		[Parameter(Position=2, Mandatory=$true)]
		[ValidateNotNull()]
		[System.String]
		$To
	)
	try{
	#Grabbing roles from an to in array
	$ArrRolesFrom = Get-VIRole -Server $From |?{$_.IsSystem -eq $False}
	$ArrRolesTo = Get-VIRole -Server $To |?{$_.IsSystem -eq $False}
	
	#Checking for existing roles
	foreach ($Role in $ArrRolesFrom){
		if($ArrRolesTo|where{$_.Name -like $role})
			{
		Logwrite -Error "$Role already exists on $To"
		logwrite -Info "Checking permissions for $role"
			[string[]]$PrivsRoleFrom = Get-VIPrivilege -Role (Get-VIRole -Name $Role -Server $From) |%{$_.id}
			[string[]]$PrivsRoleTo = Get-VIPrivilege -Role (Get-VIRole -Name $Role -Server $To) |%{$_.id}
				foreach ($Privilege in $PrivsRoleFrom){
					if ($PrivsRoleTo | where {$_ -Like $Privilege})
					{
					Logwrite -Error "$Privilege already exists on $role"
					}
					else
					{
						#Setting privileges
						Set-VIRole -Role (Get-VIRole -Name $Role -Server $To) -AddPrivilege (Get-VIPrivilege -Id $PrivsRoleFrom -Server $To)|Out-Null
						Logwrite -Success "Setting $privilege on $role"
					}
				}
			}
			else
			{
				#Creating new empty role
				New-VIrole -Name $Role -Server $To|Out-Null
				Logwrite -Success "Creating $Role on $To" 
				Logwrite -Info "Checking permissions for $role"
				[string[]]$PrivsRoleFrom = Get-VIPrivilege -Role (Get-VIRole -Name $Role -Server $From) |%{$_.id}
				[string[]]$PrivsRoleTo = Get-VIPrivilege -Role (Get-VIRole -Name $Role -Server $To) |%{$_.id}
				foreach ($Privilege in $PrivsRoleFrom)
				{
					if ($PrivsRoleTo|where {$_ -Like $Privilege})
					{
						Logwrite -Error "$Privilege already exists on $role"
					}
					else
					{
					#Setting privileges
					Set-VIRole -role (get-virole -Name $Role -Server $To) -AddPrivilege (get-viprivilege -id $PrivsRoleFrom -server $To)|Out-Null
					logwrite -success "Setting $privilege on $role"
					}
				}
			}
		}
	}
	catch 
	{
		throw
	}
}

AD authentication and Windows Passthrough VCSA appliance

While we are deploying a new vCenter 6.0 environment we planned to make a setup like this:

2 physical sites, on both sites we create a vCenter appliance and a vCenter Platform Service controller. Both the PSC are joined to the same (replication) domain.

Deployment worked perfect, logged in as SSO user, and configured the LDAP settings so we could login with our domain accounts.

Wow easy as hell, but hey a colleague mentions he cannot login while using the checkbox “use windows credentials”. We got an error

Problem:

You see a popup with the error:
Window session credentials cannot be used to log into this server. Enter a user name and password

Troubleshooting:

Well I tried a lot of VMware KB’s like :
http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2050701

And also a few others but still with no real result.

Then I found out on a few different sites you need to join the appliances to your Active Directory Domain. That makes sense, searched for some guides and  you can do it by GUI but then only for the PSC’s this didn’t solve the problem.

For testing I started to deployed an embedded VCSA and configured that the way I did with external version. Joined the machine to the domain, tested this and wow that worked.

So somewhere in the communication flow between VC – PSC – AD something will go wrong. The AD connection should be good as it worked flawless with the embedded version (assumption) so the problem should be something between VC and PSC.

I remembered a note on a site to join ALL nodes from your vSphere environment to AD to make it work. But damn, why does the GUI only show the PSC’s ? Makes sense that only the PSC are connected to a domain and do the authentication.

A colleague then tied the knots and a found a command to join AD from command line. Hey I already saw it, but what if we also look on the vCenter server to see if we can join them too.

Wow the command is there.

/opt/likewise/bin/domainjoin-cli

So let’s try again :

  • Re-deploy 2 VC’s and 2 PSC
  • Login with SSH
  • Join PSC’s to domain, join VC’s to domain
  • /opt/likewise/bin/domainjoin-cli join <domain><domain admin user> 
  • Restart all servers
  • Login with SSH
  • Query DC to see if the join was succesfull
    /opt/likewise/bin/domainjoin-cli query
  • Configure SSO
  • Test …….BAM works!

Solution:

Join all nodes (vCenter servers & Platform Service Controllers) to the Active Directory Domain.

/opt/likewise/bin/domainjoin-cli join <domain><domain admin user>

 

Bonus : For troubleshooting I checked a lot of log files, here is a good list of log file locations:

http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2110014

PowerCLI Start and stop VM using get-view

Intro

When trying to stop and start a bunch of servers I noticed that using the normal commands it took a while to shutdown all VM’s mostly because the tasks are started after each other. When You select the bunch of VM’s in vCenter, right click and select shutdown it will almost instantly start the requests tasks.

get-vm | shutdown-vmguest -confirm:$false

Fine-Tuning

I have test set of 5 CentOS Virtual machines which are all named with CENTOS in the name.

Using the measure-command command I measured the time it took to run the commands.

Command TotalSeconds
measure-command {(get-vm -name centos*)|Start-VM -Confirm:$false -RunAsync}|select totalseconds|ft -a 3,32
measure-command {(get-vm -name centos*)|Shutdown-VMGuest -Confirm:$false}|select totalseconds|ft -a 6,18

Not too bad you would say using 5 VM’s

But let’s extrapolate this for more machines

Amount VM Start(Sec) Stop(Sec) Start(Min) Stop(Min)
1,00 0,66 1,24 0,01 0,02
50,00 33,20 61,80 0,55 1,03
100,00 66,40 123,60 1,11 2,06
500,00 332,00 618,00 5,53 10,30
1000,00 664,00 1236,00 11,07 20,60

As you can see this is gaining a lot more time.

Now I build 2 commands which do exact the same thing only using the get-view commands.

measure-command {(Get-View -ViewType VirtualMachine -property Name -Filter @{“Name” = “CentOS*”}).ShutdownGuest()} |select totalseconds|ft -a 2,33
measure-command {(Get-View -ViewType VirtualMachine -property Name -Filter @{“Name” = “CentOS*”}).PowerOnVM_Task($null)} |select totalseconds|ft -a 1,64

When we extrapolate this one we see a lot of change

Aantal VM Start(Sec) Stop(Sec) Start(Min) Stop(Min)
1,00 0,2 0,04 0,00 0,00
50,00 10,00 2,00 0,17 0,03
100,00 20,00 4,00 0,33 0,07
500,00 100,00 20,00 1,67 0,33
1000,00 200,00 40,00 3,33 0,67

 Conclusion

Starting VM’s from 11 to 3 minutes and stopping from 20,60 minutes to 0,67 minutes. That’s an incredible time win when doing this with a lot of servers.

As you can see if you have a small set of VM’s or time enough (batch jobs) it might be easier to use the common cmdlets. Those will do the actions you want plus it’s more readable for colleague’s who can understand Powershell but using the VI APIs might be a bridge too far.

I haven’t been able to test it in real practice at the moment, so the extrapolation is based on the amount of time it took to power on and shutdown 5 Test VM’s.

 

sVmotion single files to another datastore PowerCLI oneliner

I needed to move a lot of VM disks from one to another datastore, and was too lazy to do it with the gui, and click on advanced etc.
So I created a nice oneline which helped me move them pretty good, (of course you can add -runasync) to do more disks simultaneously

get-HardDisk -vm (get-vm -Datastore "old_Datastore")|where {$_.filename -match "old_Datastore"} | Move-HardDisk -Datastore "New_Datastore" -confirm:$false

Exporting CSV files with your default delimiter

Normally when you export a csv file in powershell it uses the default delimiter comma, unless you use the -delimiter parameter to use another delimiter.

Depending on your language settings tools like Excel use a different delimiter. You can find these settings in your region/language settings -> Formats -> additional settings. Here is a field with “List seperator” which shows you the list separator selected.

You also can retrieve this with the powershell command below:

[Powershell](Get-Culture).TextInfo.ListSeparator[/powershell]

Because of this and switching between servers/workstations with different language settings this can be frustrating sometimes. This is why the –useculture parameter is available

Use the list separator for the current culture as the item delimiter. The default is a comma (,).

This parameter is very useful in scripts that are being distributed to users worldwide. To find the list separator for a culture, use the following command:

export-csv -useculture

This uses your local delimiter as delimiter for your export CSV, so as soon as you doubleclick it and it opens in excel it is already correctly seperated.

HP-AMS older then DL380Gen8 Hardware

HP-AMS keeps restarting

Problem

A few weeks ago we started to deploy HP Custom Image for ESXi 5.1.0 Update 2 on all our ESXi hosts. Everything seemed to work without problems until a colleague recently discovered in the logfiles that the HP-AMS provider keeps restarting every 5 minutes and gives an error message that it can’t start because it only works on.

We also noticed the problem only occured on ESXi hosts which are not HP DL380Gen8. So DL585 G5,G6,G7 gave these errors. Makes sense, the error also notices that it runs on Gen8 and older!

Solution

Luckily I found a VMWare article KB2085618 which described our problem:

Too bad the only solution is to remove the Agentless Management agent…by hand on the command line on 50+ ESXi hosts.

Damn! I was too lame to do this by hand so build a little powerCLI script. It’s not completed yet or error free. It was just a quick and dirty solution for fast results. So it’s not yet completed, but would like to share it already as it is faster then enabling SSH everywhere, connecting to ESXi hosts, insert commands, reboot etc.

Script

Pre-requirements

– Connect to your vCenter

– Put host in maintenance mode

– Load the module of function

– Plink installed and edited the script to use the right Plink directory

Download Plink here:

http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html

 


Function Enable-TSM {
Param (
[parameter(valuefrompipeline = $true, mandatory = $true,
HelpMessage = "Enter an ESX(i) entity")]
[PSObject]$VMHost,
[switch]$Local)

process {
switch ($VMHost.gettype().name) {
"String" {
if ($Local) {$VMHost = Get-VMHost -Name $VMHost | Enable-TSM -Local}
else {$VMHost = Get-VMHost -Name $VMHost | Enable-TSM}
}
"VMHostImpl" {
if ($Local) {
$VMHost | Get-VMHostService | Where {$_.Key -eq "TSM"} | %{
if ($_.running -eq $false) {
$_ | Start-VMHostService -Confirm:$false | Out-Null
Write-Host "$($_.Label) on $VMHost started"
}
else {Write-Warning "$($_.Label) on $VMHost already started"}
}
}
else {
$VMHost | Get-VMHostService | Where {$_.Key -eq "TSM-SSH"} | %{
if ($_.running -eq $false) {
$_ | Start-VMHostService -Confirm:$false | Out-Null
Write-Host "$($_.Label) on $VMHost started"
}
else {Write-Warning "$($_.Label) on $VMHost already started"}
}
}
}
default {throw "No valid type for parameter -VMHost specified"}
}
}
}


Function Disable-TSM {
Param (
[parameter(valuefrompipeline = $true, mandatory = $true,
HelpMessage = "Enter an ESX(i) entity")]
[PSObject]$VMHost,
[switch]$Local)

process {
switch ($VMHost.gettype().name) {
"String" {
if ($Local) {$VMHost = Get-VMHost -Name $VMHost | Disable-TSM -Local}
else {$VMHost = Get-VMHost -Name $VMHost | Disable-TSM}
}
"VMHostImpl" {
if ($Local) {
$VMHost | Get-VMHostService | Where {$_.Key -eq "TSM"} | %{
if ($_.running -eq $true) {
$_ | Stop-VMHostService -Confirm:$false | Out-Null
Write-Host "$($_.Label) on $VMHost stopped"
}
else {Write-Warning "$($_.Label) on $VMHost already stopped"}
}
}
else {
$VMHost | Get-VMHostService | Where {$_.Key -eq "TSM-SSH"} | %{
if ($_.running -eq $true) {
$_ | Stop-VMHostService -Confirm:$false | Out-Null
Write-Host "$($_.Label) on $VMHost stopped"
}
else {Write-Warning "$($_.Label) on $VMHost already stopped"}
}
}
}
default {throw "No valid type for parameter -VMHost specified"}
}
}
}

These functions were still in my profile so I put them on the site but were not created by me, these are only needed to enable/disable SSH.


function Get-HP{
<#
#Help file
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.String]
$VMhostName,

[switch]$Status,

[switch]$Remove
)
try {
$Hosts = Get-VMHost $VMhostName
if ($Status -eq $true){
#######Check for HP-AMS Provider Status #######
foreach ($VMHost in $Hosts){
$ESXCLI = Get-EsxCli -VMHost $VMHost
$HP = $ESXCLI.software.vib.list() | Where { $_.Name -like "hp-ams"} | Select @{N="VMHost";E={$ESXCLI.VMHost}}, Name, Version
if ($HP.name -eq "hp-ams"){
if($Hosts.Model -match "Gen8"){
Write-Host -fore Green "HP-AMS Provider found on" $HP.VMhost $hosts.model "Version:" $HP.version
}
else {
Write-Host -fore Red "Please remove HP-AMS Provider found on" $HP.VMhost $hosts.model "Version:" $HP.version
}
}
else{
Write-Host -ForegroundColor Red "No HP-AMS Provider found on $HP.VMhost $hosts.model"
}
}
}
elseif ($Remove -eq $true){
#######Remove option#######
# Maintenance mode check

Write-Host "Checking Maintenance mode"
if ((Get-VMHost $hosts | select ConnectionState).Connectionstate -ne "Maintenance")
{throw "Put host in maintenance mode please"}
else
{
Write-Host -ForegroundColor Green "Maintenance mode OK"
#2 Enable SSH
Enable-TSM $Hosts
if ((Get-VMHostService -VMHost $Hosts|?{$_.key -eq "TSM-SSH"}).running -eq "True")
{Write-Host -ForegroundColor Green "SSH running succesfull"}
else
{Write-Host -ForegroundColor Red "SSH failed starting"}

#3     HP Service stoppen middels Plink actie
# Creating alias for plink and test path
if (-not (test-path "D:\Putty\plink.EXE")) {throw "D:\Putty\plink.EXE needed"}
set-alias plink "D:\Putty\plink.EXE"
$Str1 = 'echo Y | plink -pw Password -l root '
$Stop = ' /etc/init.d/hp-ams.sh stop'
$Server = $hosts.name
$command= $str1+$server+$Stop
$output = Invoke-Expression -Command $command
$output

#4Verwijderen HP service
Write-Host "Starting removal"
$Str2 = 'plink -pw Password -l root '
$Remover = ' esxcli software vib remove -n hp-ams'
$command= $str2+$Server+$Remover
$output1 = Invoke-Expression -Command $command
$output1
if ($output1 -like "*successfully*"){
Write-Host -ForegroundColor green "Removal completed succesfully"
if ($output1 -like "*reboot*")
{
Write-Host -ForegroundColor Yellow "Reboot required and starting now"
Restart-VMhost -VMHost $Hosts -Confirm:$false|Out-Null
Write-Host -ForegroundColor Yellow "Restart started"
}
Else{
write-host "Possible dry-run?"
}
}
Else {
if ($output1 -like "*NoMatchError*"){
Write-Host "Nothing to do already removed probably restart required";Disable-TSM $Hosts
}
else{}
}

}
}
else {
Write-Host "No switch parameter found, use -remove or -status";Disable-TSM $Hosts
}
}
catch {throw}
}

Switches

-status : Checks the status of the host, is the agent installed and which model is the host.

-remove : Checks if host is in maintenance mode, stops the HP-AMS service, uninstalls the HP-AMS service and restarts the VMhost

Execution

Example for a DL585G5

get-hp -VMhostName esx1.net –Status
Please remove HP-AMS Provider found on esx1.net ProLiant DL585 G5 Version: 500.10.0.0-18.434156

Example for a DL380 Gen8

get-hp -VMhostName esx2.net -Status
HP-AMS Provider found on esx2.net ProLiant DL380p Gen8 Version: 500.10.0.0-18.434156

#Remove exection (need to paste)

Add or subtract date/time in Excel and Powershell

Excel

Manipulate the date

Let’s say we have a field with a date, for example I take an easy date like : 1-1-2011 I put it in field A1
Now how to add/subtract this value in another field.

Depending on your language :

Enter the following formula to create a new date property field (of course another field)

=DATE(YEAR(A1);MONTH(A1);DAY(A1))

1-1-2014 1-1-2014

So now we have 2 fields with the same date. Now let’s add something to the original date.

For this example I add +5 to the Year, Month and Day.

=DATE(YEAR(A1)+5;MONTH(A1)+5;DAY(A1)+5)

This results in :

1-1-2014 6-6-2019

The same trick can be used to only edit one property of course, to subtract we use -5

=DATE(YEAR(A1)-5;MONTH(A1)-5;DAY(A1)-5)

1-1-2014 27-7-2008

Manipulate the time

As you can see it’s pretty easy the same can be done with the time property

=TIME(HOUR(A2)+5;MINUTE(A2)+5;SECOND(A2)+5)

Or

=TIME(HOUR(A2)5;MINUTE(A2)5;SECOND(A2)5)

Powershell

Let’s create a date/time variable

$date = get-date

The $date variable contains a lot of properties

PS C:\> $date|select *
DisplayHint : DateTime
DateTime    : maandag 3 november 2014 14:02:14
Date        : 3-11-2014 0:00:00
Day         : 3
DayOfWeek   : Monday
DayOfYear   : 307
Hour        : 14
Kind        : Local
Millisecond : 447
Minute      : 2
Month       : 11
Second      : 14
Ticks       : 635506201344476042
TimeOfDay   : 14:02:14.4476042
Year        : 2014

Now we can use the “add Methodes to manipulate the $date variable”

PS C:\> $date|gm
TypeName: System.DateTime

Name                 MemberType     Definition
----                 ----------     ----------
Add                  Method         datetime Add(timespan value)
AddDays              Method         datetime AddDays(double value)
AddHours             Method         datetime AddHours(double value)
AddMilliseconds      Method         datetime AddMilliseconds(double value)
AddMinutes           Method         datetime AddMinutes(double value)
AddMonths            Method         datetime AddMonths(int months)
AddSeconds           Method         datetime AddSeconds(double value)
AddTicks             Method         datetime AddTicks(long value)
AddYears             Method         datetime AddYears(int value)

etc.

As you can see there are a lot things that can be changed.

Manipulate the date

With the example of the Excel commands I just add +5 to the Year,Month,Day

$date.addyears(+5).addMonths(+5).addDays(+5)
woensdag 8 april 2020 14:02:14

Or to subtract use

$date.addyears(-5).addMonths(-5).addDays(-5)
vrijdag 29 mei 2009 14:02:14

Manipulate the time

This can be done the sameway like described above

$date.addHours(+5).addMinutes(+5).addSeconds(+5)
maandag 3 november 2014 19:07:19

Or to subtract use

$date.addHours(-5).addMinutes(-5).addSeconds(-5)
maandag 3 november 2014 8:57:09

Hopefully someone finds it useful.

1 2 3