lElOUCHE_79
Enthusiast
Enthusiast

Create Snapshot based on CSV files

Jump to solution

Hello,

for some requirement we need always to have LOGs for scripts that we are running 🙂

I have the below script that is supposed to create snapshots based on CSV files, unfortunately no snapshots taken and no error message 🙂

 

The idea of the script is that once Snapshots are created later we will remove them based on their name and snapshot description details

 

 

 

#---------------------------------------------------------[Initialisations]--------------------------------------------------------
[console]::BackgroundColor = "Black"
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls, [System.Net.SecurityProtocolType]::Tls11, [System.Net.SecurityProtocolType]::Tls12
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false
Clear-Host

# Set debug action to continue if you want debug messages at console
$DebugPreference = "SilentlyContinue"

# Get filename of script and use the same name for the logfile without file extension
$ScriptName = $MyInvocation.MyCommand.Name
$ScriptName = $ScriptName.Replace(".ps1","")
#Get date today for logfile in format day-month-year_hours-minutes, e.g. 24-11-2015_19-30
$Today = get-date -format d-M-yyyy_HH-mm
Add-Type -AssemblyName System.Windows.Forms

$StartTime = Get-Date    
#----------------------------------------------------------[Declarations]----------------------------------------------------------
# Define log file
$FilePath = ".\LOGs-Output"
$ScriptLOG = "$($ScriptName)_$($Today).log"
$LogFile = Join-Path -Path $FilePath -ChildPath $ScriptLOG
#---------------------------------------------------------[Function Write-Log]------------------------------------------------------
function Write-Log {
    [CmdletBinding()]
    Param
    (      
        [Parameter(Mandatory = $true)]
        [string] $FilePath,

        [Parameter(Mandatory = $true)]
        [string] $Message,

        [ValidateSet("Info", "Warning", "Error", "Success", "Control")]
        $Level = "Info",

        [switch]$Clear,

        [switch]$StartInfo,

        [switch]$StartControl
    )

    if (Test-Path -Path (Split-Path -Path $FilePath -Parent)) {
        $FormattedDate = Get-Date -Format "[yyyy-MM-dd][HH:mm:ss]"
        $OutString = "$FormattedDate - $Level - Folder Exists"
        $OutString | Out-File -FilePath $FilePath -Append
      }
      else {
        New-Item -Path '.\LOGs-Output' -ItemType Directory
        $FormattedDate = Get-Date -Format "[yyyy-MM-dd][HH:mm:ss]"
        $OutString = "$FormattedDate - $Level - Folder Created"
        $OutString | Out-File -FilePath $FilePath
    }

    if ($Clear) {
        Clear-Content -Path $FilePath
    }

    if ($StartInfo) {
        [string[]]$StartText = @()
        $StartText += "$("#" * 100)"
        $StartText += "# Running script : $($MyInvocation.ScriptName)"
        $StartText += "# Start time : $(Get-Date)"  
        $StartText += "# Executing account : $([Security.Principal.WindowsIdentity]::GetCurrent().Name)"
        $StartText += "# ComputerName : $env:COMPUTERNAME"
        $StartText += "$("#" * 100)"
        $StartText | Out-File -FilePath $FilePath -Append
    }

    $FormattedDate = Get-Date -Format "[yyyy-MM-dd][HH:mm:ss]"
    $OutString = "$FormattedDate - $Level - $Message"
    $OutString | Out-File -FilePath $FilePath -Append

    switch ($Level) {
        "Info" { Write-Host $OutString -ForegroundColor Gray ; break }
        "Warning" { Write-Host $OutString -ForegroundColor Yellow; break }
        "Error" { Write-Host $OutString -ForegroundColor Red; break }
        "Success" { Write-Host $OutString -ForegroundColor Green; break }
        "Control" { Write-Host $OutString -ForegroundColor Cyan; break }
        Default { Write-Host $OutString; break }
    }
   
}
#-----------------------------------------------------------------------------------------------------------------------------------
Write-Log -FilePath $LogFile -Message "Script started by $([Environment]::UserName) on $([Environment]::MachineName)" -StartInfo
######################################
if (Get-Module -ListAvailable -Name VMware.PowerCLI) {
    Write-Log -FilePath $LogFile -Message "[+] PowerCLI module exists`n" -Level Success
}
else {
    Write-Log $FilePath $LogFile -Message "[-] Module does not exist. PowerCLI installation..." -Level Warning
    Install-Module -Name VMware.PowerCLI -Force
    Set-PowerCLIConfiguration -InvalidCertificateAction:Ignore
}
Import-Csv -Delimiter ";" -Path ".\VM_List\VMs.csv" |
    ForEach-Object -Process {
  Get-VM -Name $_.VMName | New-Snapshot -Name "Snapshot Description" -Description "Created $(Get-Date)" -Confirm:$false
}

 

0 Kudos
2 Solutions

Accepted Solutions
LucD
Leadership
Leadership

On the 1st row you should have the name of the column.
No need for a separator when the CSV only has 1 column

 

VMName
VM_1
VM_2

 


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

View solution in original post

LucD
Leadership
Leadership

Yes, I'm afraid so.
Try something like this

Write-Log -FilePath $LogFile -Message "############# creates a new snapshot of virtual machine #############" -Level Control

Import-Csv -Path ".\VM_List\VMs.csv" -UseCulture | ForEach-Object -Process {
    $snapshot = Get-VM -Name $_.VMName | Get-Snapshot -Name "Created $(Get-Date -Format 'yyyy.MM.dd')" -ErrorAction SilentlyContinue
    if ($snapshot) {
        <# Snapshots Exists, remove before processing #>
        Write-Log -FilePath $LogFile -Message "[-] Snapshots found'n" -Level Info
        Remove-Snapshot -Snapshot $snapshot -Confirm:$false
        Write-Log -FilePath $LogFile -Message "[-] $VM Snapshot removed successfully'n" -Level Success
    }
    New-Snapshot -VM $_.VMName -Name "Created $(Get-Date -Format 'yyyy.MM.dd')" -Description "Created $(Get-Date -Format 'yyyy.MM.dd')"
    Write-Log -FilePath $LogFile -Message "[+] $VM Snapshot created successfully'n" -Level Success
}


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

View solution in original post

0 Kudos
30 Replies
LucD
Leadership
Leadership

Are snapshots created when you just do this?

Import-Csv -Delimiter ";" -Path ".\VM_List\VMs.csv" |
    ForEach-Object -Process {
  Get-VM -Name $_.VMName | New-Snapshot -Name "Snapshot Description" -Description "Created $(Get-Date)" -Confirm:$false
}


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

0 Kudos
lElOUCHE_79
Enthusiast
Enthusiast

Hello

In VMs.csv I have 2 VMs and I got the below error message

lElOUCHE_79_0-1674641876007.png

 

0 Kudos
LucD
Leadership
Leadership

Do you have an empty line in the CSV?
What exactly is in the CSV?


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

0 Kudos
lElOUCHE_79
Enthusiast
Enthusiast

no empty line in the CSV

in the CSV file I have

VM_1;

VM_2;

0 Kudos
LucD
Leadership
Leadership

On the 1st row you should have the name of the column.
No need for a separator when the CSV only has 1 column

 

VMName
VM_1
VM_2

 


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

lElOUCHE_79
Enthusiast
Enthusiast

Thank you it's working fine 🙂

lElOUCHE_79_0-1674648746716.png

One of the VM is Powerd ON, unfortunately, I got the PowerState for both as PowerdOFF

 

It's a normal behavior?

0 Kudos
LucD
Leadership
Leadership

No, that is not normal.
When the VM is powered on, the Get-VM (or New-Snapshot) should not show it as powered off.

Does a Get-VM show it as powered on?


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

0 Kudos
lElOUCHE_79
Enthusiast
Enthusiast

Get-VM show it as powerd on

strange

0 Kudos
LucD
Leadership
Leadership

I just did some tests, and indeed the I also see the PoweredOff state, although the VM is powered on.
Seems to powerstate that is shown on the output of New-Snapshot, indicates the state of the Memory switch.

Without the -Memory switch, the output of New-Snapshot always shows "poweredoff".
With the -Memory switch present, powerstate shows "poweredon" when the VM was powered on during the snapshot, and "poweredoff" when the VM was powered off.

A bit confusing


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

0 Kudos
lElOUCHE_79
Enthusiast
Enthusiast

Ah ! Ok then I should add -Memory switch, I made some search but not able to find how I can solve this

https://vdc-repo.vmware.com/vmwb-repository/dcr-public/85a74cac-7b7b-45b0-b850-00ca08d1f238/ae65ebd9...

 

0 Kudos
LucD
Leadership
Leadership

See Example 2 on that page


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

0 Kudos
lElOUCHE_79
Enthusiast
Enthusiast

Ah Ok , then I should add

-Memory $false

Because I will not Snapshot the virtual machine's memory 🙂 

And I should have something like this :

 

 

Import-Csv -Delimiter ";" -Path ".\VM_List\VMs.csv" |
    ForEach-Object -Process {
  Get-VM -Name $_.VMName -Memory $false | New-Snapshot -Name "Snapshot Description" -Description "Created $(Get-Date)" -Confirm:$false
}

 

 

0 Kudos
LucD
Leadership
Leadership

That -Memory parameter goes on the New-Snapshot cmdlet.
But setting it to $false will show the VM as being powered off in the snapshot.


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

lElOUCHE_79
Enthusiast
Enthusiast

you are right

lElOUCHE_79_0-1674677066132.png

 

 

0 Kudos
lElOUCHE_79
Enthusiast
Enthusiast

Hi Luc

I corrected it and it's working fine now 🙂

 

Import-Csv -Delimiter ";" -Path ".\VM_List\VMs.csv" |
ForEach-Object -Process {
Get-VM -Name $_.VMName | New-Snapshot -Name "Snapshot Description" -Description "Created $(Get-Date)" -Memory:$true -Confirm:$false
}

 

lElOUCHE_79_0-1674734577801.png

 

0 Kudos
lElOUCHE_79
Enthusiast
Enthusiast

@LucD 
I made some change on my script and I got an error message

 

Script:

Write-Log -FilePath $LogFile -Message "############# creates a new snapshot of virtual machine #############" -Level Control
######################################
$VMList = Get-Content -Path ".\VM_List\VMs.csv"

    foreach ($VM in $VMList) {
        $Snapshot = Get-VM -Name $_VMName | New-Snapshot -Name "Snapshot Description" -Description "Created $(Get-Date)" -Memory:$true -Confirm:$false

        if ($null -eq $Snapshot) {
            <# No Snapshots found, Create one at top level. #>
            Write-Log -FilePath $LogFile -Message "[+] No Snapshots found`n" -Level Info
            New-Snapshot($VM)
            Write-Log -FilePath $LogFile -Message "[+] $VM : Snapshots created succesfully`n" -Level Success
        }
        else {
            <# Snapshots Exists, remove before processing #>
            Write-Log -FilePath $LogFile -Message "[-] Snapshots found'n" -Level Info
            Remove-Snapshot($VM)
            Write-Log -FilePath $LogFile -Message "[-] $VM Snapshot removed successfully'n" -Level Success
            New-Snapshot($VM)
            Write-Log -FilePath $LogFile -Message "[+] $VM Snapshot created successfully'n" -Level Success
        }
 
    }
 
Error message
 
lElOUCHE_79_0-1674740347756.png

 

would you please help me to understand where's my error?

0 Kudos
LucD
Leadership
Leadership

Seems you forgot the dot in $_.VMName


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

0 Kudos
lElOUCHE_79
Enthusiast
Enthusiast

good point 🙂

Unfortunately same error 😞

0 Kudos
LucD
Leadership
Leadership

Since you seem to be reading with Get-Content now, instead of Import-Csv, there is no property named VMName.
Is the column header row still in the CSV file?
In that case you will have to skip that 1st row and then just use $_ instead of $_.VMName on the Name parameter.

But why do read a CSV file with Get-Content?


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

0 Kudos