VMware Cloud Community
DZ1
Hot Shot
Hot Shot
Jump to solution

Delete VM on the specified date

I"m trying to write a script to delete a VM on a certain date.  Currently, I want people to add this to the VM name "VMname_Delete-/1/1/14", I then search for the VM with:

Get-VM | where {$_.name -cmatch "Delete-\d\/\d\/\d"}

With that, I'm sure that the correct VM is selected, and I tested it with some VMs to make sure.  Now comes the hard part (at least for me), I want to take the date that's part of the VM name, and convert it to a [DateTime] value, and then compare it to the current date.  If they match, I want to delete the VM.  I was trying something along the lines of:

Get-VM | where {$_.name -cmatch "Delete-\d\/\d\/\d"} | foreach { $_.name -split "-"}

That of course split the dash, and on testing, I had an output similar to:

VM_Delete

1/1/14

Of course, now I don't know how to finish the rest.  I was thinking that the script would go something like:

Get-VM | where {$_.name -cmatch "Delete-\d\/\d\/\d"} | foreach {

if ( ($_.name -split "-") -as [datetime] -match (get-date -format "MM/dd/yy")  )

{Remove-VM -VM $_ -DeletePermanently}

}

I can think of the logic in my head, but of course, I just can't write it up they way I think that it should go.  Any help is appreciated. 

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

You could perhaps do something along these lines

$now = Get-Date

Get-VM | where {$_.name -cmatch "Delete-\d\/\d\/\d"} | foreach {

    $dt = [datetime]($_.Name.Split('-')[1])

    if($dt -lt $now){

        Remove-VM -VM $_ -DeletePermanently

    }

}

With the use of the index ([1]), we select the date part of the VM name.

Then we 'cast' the string to a DateTime object.

Note that this cast might cause problems, depending on the culture settings you use.

Worst case, you split the date string on the '/'  character, and then generate the DateTime object like this

$now = Get-Date

Get-VM | where {$_.name -cmatch "Delete-\d\/\d\/\d"} | foreach {

    $dummy,$day,$month,$year = $_.Name.Split('-')[1].Split('/')

    $dt = Get-Date -Day $day -Month $month -Year $year

    if($dt -lt $now){ 

        Remove-VM -VM $_ -DeletePermanently

    }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

Reply
0 Kudos
7 Replies
LucD
Leadership
Leadership
Jump to solution

You could perhaps do something along these lines

$now = Get-Date

Get-VM | where {$_.name -cmatch "Delete-\d\/\d\/\d"} | foreach {

    $dt = [datetime]($_.Name.Split('-')[1])

    if($dt -lt $now){

        Remove-VM -VM $_ -DeletePermanently

    }

}

With the use of the index ([1]), we select the date part of the VM name.

Then we 'cast' the string to a DateTime object.

Note that this cast might cause problems, depending on the culture settings you use.

Worst case, you split the date string on the '/'  character, and then generate the DateTime object like this

$now = Get-Date

Get-VM | where {$_.name -cmatch "Delete-\d\/\d\/\d"} | foreach {

    $dummy,$day,$month,$year = $_.Name.Split('-')[1].Split('/')

    $dt = Get-Date -Day $day -Month $month -Year $year

    if($dt -lt $now){ 

        Remove-VM -VM $_ -DeletePermanently

    }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
DZ1
Hot Shot
Hot Shot
Jump to solution

Thanks for your help, what you did makes sense, but I'm having a slight issue.  I forgot that with vCenter or maybe it's the host, but there is an issue with forward slash "/" when it's used in a name, vCenter will make it a percent symbol, so I decided to use dashes for the date.  But that's not where the problem is.

I've tried this as a test, just to play with splitting the name and making it into datetime

$now = Get-Date

$name  = "Delete-09-09-13" | foreach {

$dt=[datetime]($name.split("-",2)[1])

if ($now.Month -eq $dt.Month) {

Write $_

}

}

When I try this I get an error:

You cannot call a method on a null-valued expression

It seems as if $name turns into a $null

My thinking was that I was going to match the datetime with the Month, Day, and year, and as long as those matched, I would delete the VM.

Here is what I tried with your script:

$now = Get-Date

Get-folder Test | Get-VM | where {$_.name -cmatch "Delete-\d\-\d\-\d"} | foreach {

$dt=[datetime]($_.name.Split("-",2)[1])

if ($dt -lt $now) {

Remove-VM

}

}

I get this error:

Cannot convert value "Delete-9-9-13" to type "System.DateTime". Error: "The string was not recognized as a valid DateTime. There is an unknown word starting at index 0."

It works fine when I go right to the command line and I try something like this:

$Name = "Delete-09-09-13"

$dt = [datetime]($name.split("-",2)[1])

That will make $dt into a date, and if I created a variable with Get-Date, I can match up the Month, Day, and Year, but when it's all in a script, it errors.

Reply
0 Kudos
DZ1
Hot Shot
Hot Shot
Jump to solution

After some testing, the script below runs fine on the first pass, but if ran a second time, it will throw the error You cannot call a method on a null-valued expression

What doesn't make sense is if I'm assigning a new variable every time, it should work every time, at least it seems as if it should.  I stepped through the lines and when the new variable is created with the contents "Delete-09-09-13", it is initially a string, and it shows the value of "Delete-09-09-13", but after that first run, the value shows as a PSCustomobject, it it never shows a string again, even though I thought it should override the variable and create a new one.

$now = Get-Date

$test = "Delete-09-09-13" | % {

$dt=[datetime]($test.split("-",2)[1])

if ($now.Month -eq $dt.month) {

Write-Host $dt.Month, $dt.Day, $dt.Year #this shows up fine the first time, on subsequent runs, I get an error, but it still writes the dates

}

}

Reply
0 Kudos
DZ1
Hot Shot
Hot Shot
Jump to solution

Interesting, I tried a small change, and I moved [datetime] in front of the $dt, and it seems to be working.  Thanks for your help, but I'm curious why it works this way. 

$now = Get-Date

Get-folder Test | Get-VM | where {$_.name -cmatch "Delete-\d\-\d\-\d"} | foreach {

[datetime]$dt=($_.name.Split("-",2)[1])

if ($dt.Month -eq $now.Month) {

Remove-VM -VM $_ -Confirm

}

}

Reply
0 Kudos
DZ1
Hot Shot
Hot Shot
Jump to solution

Typed before I truly tested.  Although, the script works, I am still getting this error:

Cannot convert value "Delete-09-09-13" to type "System.DateTime". Error: "The string was not recognized as a valid DateTime. There is an unknown word starting at index 0."

Overall, this is the main part of the script, and again, thanks for your help

$now = Get-Date

Get-folder Test | Get-VM | where {$_.name -cmatch "Delete-\d\d\-\d\d\-\d\d"} | foreach {

[datetime]$dt=($_.name.Split("-",2)[1])

if ($dt.Month -eq $now.Month -and $dt.Day -eq $now.Day -and $dt.Year -eq $now.Year) {

Remove-VM -VM $_ -Confirm

}

}

I receive the notification to remove the VM, but I also receive the error message.  I guess I could just silientlycontinue, but I'm curious why this happens.  I've tried the script on 2 VMs, and it always works, I just don't know why the message comes up.  In any event, thanks for leading me on the right path.  Smiley Happy

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Why did you have the ForEach loop (%) in the previous test script ?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
DZ1
Hot Shot
Hot Shot
Jump to solution

I just left it there since it was going to be multiple VMs anyway, I just didn't take it out for the test.

I made some more changes because we have some VMs that may have a dash already in the name, and since I don't know how many dashes may be in the name, it was easier to use an underscore, and then use a dot(.) for the date separator.  Overall, sit seems to work very well.  I'm also using a 2 digit date, I want to make 100% sure that I only pull the VMs that need to be deleted, and if the date isn't correct, I'll just have an email send out the name, and those can be deleted manually.

I still have to complete the script, but the hard part is over thanks to you.

$now = Get-Date

Get-folder Test | Get-VM | where {$_.name -cmatch "Delete_\d\d\.\d\d\.\d\d"} | foreach {

[datetime]$dt=($_.name.Split("_",2)[1])

if ($dt.Month -eq $now.Month -and $dt.Day -eq $now.Day -and $dt.Year -eq $now.Year) {

Remove-VM -VM $_ -Confirm

}

else

{Send-MailMessage -SmtpServer '12.8.1.6' -From "<@s.com>" -To "<s@c.com>" -Subject VMs -Body $_.name}

}

Reply
0 Kudos