VMware Cloud Community
lElOUCHE_79
Enthusiast
Enthusiast
Jump to solution

Create Snapshot based on CSV files

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
}

 

Reply
0 Kudos
30 Replies
lElOUCHE_79
Enthusiast
Enthusiast
Jump to solution

Thanks for the reply

Is the column header row still in the CSV file?
yes, the structure is like this

VMName

VM1;

VM2;

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

I'm reading from CSV file because I will have to create Snapshots for specific VMs

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

But normally you read a CSV file with Import-Csv (as I posted in the original snippet), why did you change it to Get-Content?


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

lElOUCHE_79
Enthusiast
Enthusiast
Jump to solution

ecause I didn't managed to use Import-Csv  in loop 😞

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

My snippet is using a loop (Foreach-Object)

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

Reply
0 Kudos
lElOUCHE_79
Enthusiast
Enthusiast
Jump to solution

My bad, I mean this portion of script

    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
        }
    }
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You can still use that loop I posted.

Also, when looking for an existing snapshot, just using Get-Date will include the seconds in the name.
So changes are low that an existing snapshot from that same day will be found.

As an alternative

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($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
}


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

lElOUCHE_79
Enthusiast
Enthusiast
Jump to solution

for sure I'm missing something or doing things in wrong way

 

lElOUCHE_79_0-1674754458057.png

 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

I just copied that from your code.

What is the meaning of this New-Snapshot($vm) call?
Is that a function you defined?


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

Reply
0 Kudos
lElOUCHE_79
Enthusiast
Enthusiast
Jump to solution

New-Snapshot($vm) I'm using this call to create new snapshot by searching the vm from vm list 

 

I believe I'm doing it incorrectly 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
lElOUCHE_79
Enthusiast
Enthusiast
Jump to solution

Thank you @LucD 

Reply
0 Kudos