7 Replies Latest reply on Sep 9, 2013 11:33 AM by DZ1

    Delete VM on the specified date

    DZ1 Hot Shot

      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. 

        • 1. Re: Delete VM on the specified date
          LucD Guru
          Community WarriorsUser ModeratorsvExpert

          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: http://lucd.info | Twitter: @LucD22 | PowerCLI Reference co-author: http://tinyurl.com/hkn4glz
          • 2. Re: Delete VM on the specified date
            DZ1 Hot Shot

            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.

            • 3. Re: Delete VM on the specified date
              DZ1 Hot Shot

              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

              }

               

               

              }

              • 4. Re: Delete VM on the specified date
                DZ1 Hot Shot

                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

                }

                 

                 

                }

                • 5. Re: Delete VM on the specified date
                  DZ1 Hot Shot

                  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. 

                  • 6. Re: Delete VM on the specified date
                    LucD Guru
                    Community WarriorsvExpertUser Moderators

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

                    Blog: http://lucd.info | Twitter: @LucD22 | PowerCLI Reference co-author: http://tinyurl.com/hkn4glz
                    • 7. Re: Delete VM on the specified date
                      DZ1 Hot Shot

                      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}

                      }