function New-ITDVMwareVMSnapshotTaskV3Prd { [CmdletBinding()] Param ( [int] $Id, [PSCredential] $SharePointCredential ) begin { $UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" $InvokeRestMethodParams = @{ Uri = $UrlContextInfo; Method = "Post"; UseBasicParsing = $true; } If ($SharePointCredential) { $InvokeRestMethodParams += @{Credential = $SharePointCredential } } Else { $InvokeRestMethodParams += @{UseDefaultCredentials = $true } } $RequestDigest = Invoke-RestMethod @InvokeRestMethodParams $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue $UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')" $InvokeRestMethodParams = @{ Uri = $UrlList; UseBasicParsing = $true; } If ($SharePointCredential) { $InvokeRestMethodParams += @{Credential = $SharePointCredential } } Else { $InvokeRestMethodParams += @{UseDefaultCredentials = $true } } $List = Invoke-RestMethod @InvokeRestMethodParams $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName $UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,NotifyEmail&$expand=Author/Id' $InvokeRestMethodParams = @{ Uri = $UrlListItem; Method = "Get"; UseBasicParsing = $true; Headers = @{ "Accept" = "application/json;odata=verbose" }; } If ($SharePointCredential) { $InvokeRestMethodParams += @{Credential = $SharePointCredential } } Else { $InvokeRestMethodParams += @{UseDefaultCredentials = $true } } $ListItems = ((Invoke-RestMethod @InvokeRestMethodParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results $header = @{ "accept" = "application/json;odata=verbose" "X-RequestDigest" = $RequestDigest "IF-MATCH" = '*' "X-HTTP-Method" = "MERGE" } } process { $SPListItem = $ListItems | Where-object Id -eq $Id $VMName = $SPListItem.Title $SnapTime = [DateTime]$SPListItem.DateTime $NotifyEmail = $SPListItem.Author.Email If ($SPListItem.NotifyEmail) { $NotifyEmail = $NotifyEmail + ';' + $SPListItem.NotifyEmail } try { $SnapName = "AutoSnap_" + $SPListItem.ID $SnapExpireDateTime = $SnapTime.AddDays($SPListItem.Duration) If ($SnapExpireDateTime.DayOfWeek -eq "Saturday" -or $SnapExpireDateTime.DayOfWeek -eq "Sunday") { $SnapExpireDateTime = $SnapExpireDateTime.AddDays(2) } $SnapDeleteDateTime = $SnapExpireDateTime.AddDays(2) $SnapDescription = [PSCustomObject]@{ Number = $Id; AutoExpire = $SnapExpireDateTime.ToLocalTime(); AutoDelete = $SnapDeleteDateTime.ToLocalTime(); } | ConvertTo-Json $snapMemory = $false $snapQuiesce = $false Write-Warning $VMName Write-Warning $SnapName Write-Warning ("SharePoint: " + $SnapTime) If ($SnapTime -lt (Get-Date)) { $SnapTime = (Get-Date).AddSeconds(30) } Write-Warning ("PowerShell: " + $SnapTime) $VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | Sort-Object Name | Select-Object -First 1).Name } $VIServer = $VM.Uid.split('@')[1].split(':')[0] # prep for SharePoint Record status update $UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($Id)" $InvokeRestMethodParams = @{ Uri = $UrlItem; Method = "Get"; Headers = @{ "Accept" = "application/json;odata=verbose" } UseBasicParsing = $true; #Credential = $SharePointCredential } If ($Credential) { $InvokeRestMethodParams += @{Credential = $SharePointCredential } } Else { $InvokeRestMethodParams += @{UseDefaultCredentials = $true } } # actual creation of vCenter task $si = Get-View ServiceInstance -Server $VIServer $scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager -Server $VIServer $spec = New-Object VMware.Vim.ScheduledTaskSpec $spec.Name = $SnapName, $VMname -join '_' $spec.Description = "$SnapDescription" $spec.Enabled = $true $spec.Notification = $NotifyEmail $spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler $spec.Scheduler.runat = $SnapTime $spec.Action = New-Object VMware.Vim.MethodAction $spec.Action.Name = "CreateSnapshot_Task" @($SnapName, $SnapDescription, $SnapMemory, $SnapQuiesce) | ForEach-Object { $arg = New-Object VMware.Vim.MethodActionArgument $arg.Value = $_ $spec.Action.Argument += $arg } $scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec) Start-Sleep -Seconds 3 } catch { write-error "vCenter Snapshot Scheduled Task Creation failed default message" write-error $error[1] Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed Default Message - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov $Status = "Errored" exit } # update SharePoint record status If ($Status -ne "Errored") { $Status = "Scheduled" } [PSCustomObject]$SetRecord = @{ "__metadata" = @{type = $ListItemEntityTypeFullName }; Status = $Status; } $body = $SetRecord | ConvertTo-Json $InvokeRestMethodParams = @{ Uri = $UrlItem; Method = "Post"; Body = $body; ContentType = "application/json;odata=verbose"; Headers = $header; UseBasicParsing = $true; } If ($SharePointCredential) { $InvokeRestMethodParams += @{Credential = $SharePointCredential } } Else { $InvokeRestMethodParams += @{UseDefaultCredentials = $true } } Invoke-RestMethod @InvokeRestMethodParams $postParams = [PSCustomObject]@{ AutomationName = "Infra-VMware"; Action = 'Provisioning'; Units = 5; Platform = 'PowerShell-VMware-SnapshotNew'; } Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json) } end { } } function Update-ITDVMwareVMSnapshotTaskStatusV3Prd { [CmdletBinding()] Param ( [int] $Id, [PSCredential] $SharePointCredential ) If ($SharePointCredential) { $SnapshotList = Get-ITDVMwareSharePointSnapshotRequestList -Credential $SharePointCredential } Else { $SnapshotList = Get-ITDVMwareSharePointSnapshotRequestList } If($Id) { $ListToUpdate = $SnapshotList | Where-Object { $_.Status -eq "Scheduled" -and $_.Id -eq $Id} } Else { $ListToUpdate = $SnapshotList | Where-Object { $_.Status -eq "Scheduled" } | Sort-Object DateTime } ForEach ($SPRecord in $ListToUpdate) { $VM = $null $Taken = $null $VMName = $null $Duration = $null $Id = $null $VMSnapshot = $null $Task = $null If ( (($SPRecord.DateTime) -as [datetime]).ToLocalTime() -lt (Get-Date) ) { # If datetime has passed $VMName = $SPRecord.Title $VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } $Duration = $SPRecord.Duration $Id = $SPRecord.Id switch ($Duration) { { $Duration -ge 1 -and $Duration -le 7 } { Write-Verbose "Duration = Snapshot" #$VMSnapshots = $VM | Get-Snapshot | Where-Object Description -like "AutoSnap_$Id*" $VMSnapshots = $VM | Get-Snapshot | Where-Object {($_.Description | ConvertFrom-Json).Number -eq $Id} If (@($VMSnapshots).count -eq 1) { Write-Verbose "Exactly one snapshot match found" $Taken = $true $VMSnapshot = $VMSnapshots #$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Description -like "AutoSnap_$Id*") $Task = (Get-View (Get-View ScheduledTaskManager).ScheduledTask).info | Where-Object Name -like ("AutoSnap_$id" + '_' + $VMName) } else { if (@($VMSnapshots).count -gt 1) { Write-Error "More than one snapshot match found, abort" Exit } else { $Taken = $false Write-Verbose "Snapshot Id #$Id match not found on $VMName" Write-Error "Snapshot $Id for $VMName not found." } } } { $Duration -ge 8 } { Write-Verbose "Duration = Clone" $VMClones = Get-VM | Where-Object Name -eq ($VMName + "_AutoClone_" + $Id) If (@($VMClones).count -eq 1) { Write-Verbose "Exactly one clone match found" $Taken = $true $VMClone = $VMClones #$Task = ((Get-View ((Get-View ScheduledTaskManager).ScheduledTask)).info | where-object Name -like "AutoClone_$Id*") $Task = (Get-View (Get-View ScheduledTaskManager).ScheduledTask).info | Where-Object Name -like ("AutoClone_$id" + '_' + $VMName) ############################## REVIEW } else { if (@($VMClones).count -gt 1) { Write-Error "More than one VM clone match found, abort" Exit } else { $Taken = $false Write-Verbose "Clone Id #$Id match not found for $VMName" Write-Error "Clone $Id for $VMName not found." } } } Default { Write-Error "Duration less than zero." } } Write-Verbose "Updating SharePoint fields named Status and SnapshotTaken" $UrlContextInfo = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo" $InvokeRestMethodParams = @{ Uri = $UrlContextInfo; Method = "Post"; UseBasicParsing = $true; } If ($Credential) { $InvokeRestMethodParams += @{Credential = $SharePointCredential } } Else { $InvokeRestMethodParams += @{UseDefaultCredentials = $true } } $RequestDigest = Invoke-RestMethod @InvokeRestMethodParams $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue $UrlList = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')" $InvokeRestMethodParams = @{ Uri = $UrlList; UseBasicParsing = $true; } If ($Credential) { $InvokeRestMethodParams += @{Credential = $SharePointCredential } } Else { $InvokeRestMethodParams += @{UseDefaultCredentials = $true } } $List = Invoke-RestMethod @InvokeRestMethodParams $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName $UrlListItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' $InvokeRestMethodParams = @{ Uri = $UrlListItem; Method = "Get"; UseBasicParsing = $true; Headers = @{ "Accept" = "application/json;odata=verbose" }; } If ($Credential) { $InvokeRestMethodParams += @{Credential = $SharePointCredential } } Else { $InvokeRestMethodParams += @{UseDefaultCredentials = $true } } $ListItems = ((Invoke-RestMethod @InvokeRestMethodParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results $header = @{ "accept" = "application/json;odata=verbose" "X-RequestDigest" = $RequestDigest "IF-MATCH" = '*' "X-HTTP-Method" = "MERGE" } $UrlItem = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($Id)" $InvokeRestMethodParams = @{ Uri = $UrlItem; Method = "Get"; Headers = @{ "Accept" = "application/json;odata=verbose" } UseBasicParsing = $true; } If ($Credential) { $InvokeRestMethodParams += @{Credential = $SharePointCredential } } Else { $InvokeRestMethodParams += @{UseDefaultCredentials = $true } } [PSCustomObject]$SetRecord = @{ "__metadata" = @{type = $ListItemEntityTypeFullName }; #Status = 'Taken'; Status = If ($Taken -eq $true) { 'Taken' } Else { 'Errored' }; SnapshotTaken = $Task.PrevRunTime.ToLocalTime(); AutoExpire = ($Task.Description | ConvertFrom-Json).AutoExpire AutoDelete = ($Task.Description | ConvertFrom-Json).AutoDelete } $body = $SetRecord | ConvertTo-Json $InvokeRestMethodParams = @{ Uri = $UrlItem; Method = "Post"; Body = $body; ContentType = "application/json;odata=verbose"; Headers = $header; UseBasicParsing = $true; } If ($Credential) { $InvokeRestMethodParams += @{Credential = $SharePointCredential } } Else { $InvokeRestMethodParams += @{UseDefaultCredentials = $true } } Invoke-RestMethod @InvokeRestMethodParams } } $postParams = [PSCustomObject]@{ AutomationName = "Infra-VMware"; Action = 'Provisioning'; Units = 1; Platform = 'PowerShell-VMware-SnapshotUpdateStatus'; } Invoke-RestMethod -Uri http://itdnettools.nd.gov/services/automation-tracking.py -Method POST -Body ($postParams | ConvertTo-Json) } function New-ITDVMwareVMCloneTaskV3Prd { [CmdletBinding()] Param ( [Parameter(Mandatory = $true)] [int[]] $Id, [VMware.VimAutomation.ViCore.Impl.V1.DatastoreManagement.VmfsDatastoreImpl] $Destination, [PSCredential] $SharePointCredential, [PSCredential] $vCenterCredential ) begin { $ConnectITDvCenterParams = @{ } If ($vCenterCredential) { $ConnectITDvCenterParams += @{Credential = $vCenterCredential } } Connect-ITDvCenter @ConnectITDvCenterParams $GetITDVMwareSharePointSnapshotRequestList = @{ } If ($SharePointCredential) { $GetITDVMwareSharePointSnapshotRequestList += @{Credential = $SharePointCredential } } $List = Get-ITDVMwareSharePointSnapshotRequestList @GetITDVMwareSharePointSnapshotRequestList } process { ForEach ($i in $ID) { try { $Request = $List | where-object ID -eq $i $VMName = $Request.Title $Duration = $Request.Duration $CloneTime = [DateTime]$Request.DateTime.ToLocalTime() If ($CloneTime -lt (Get-Date)) { $CloneTime = (Get-Date).AddSeconds(30) } $CloneExpireDateTime = $CloneTime.AddDays($Duration) $CloneDeleteDateTime = $CloneExpireDateTime.AddDays(2) #$CloneDescription = ("AutoClone_" + $Request.ID + "`r" + "AutoExpire_$CloneExpireDateTime" + "`r" + "AutoDelete_$CloneDeleteDateTime") $CloneDescription = [PSCustomObject]@{ Number = $Id; AutoExpire = $CloneExpireDateTime.ToLocalTime(); AutoDelete = $CloneDeleteDateTime.ToLocalTime(); } | ConvertTo-Json $CloneVMName = ($VMName + "_AutoClone_" + $i) $VM = Get-VM -Name $VMName | Where-Object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" } $VIServer = $VM.Uid.split('@')[1].split(':')[0] $Folder = Get-Folder -Name "_Clone Request" -Server $VIServer $Datastore = $VM | Get-Datastore $DatastoreCluster = $VM | Get-DatastoreCluster If (!($Destination)) { $Destination = Get-Datastore -Server $VIServer -Name *TEMPL* } # If DSCluster, clone to cluster # doesn't fit go to TEMPL # doesn't fit, error # If dedicated lun, clone to TEMPL # doesn't fit, error If (($Destination.FreeSpaceGB * 0.90) -lt $VM.UsedSpaceGB) { # Not enough free space, error Write-Error ("Not enough free space on " + $Destination.Name) } else { $ma = New-Object VMware.Vim.MethodAction $ma.Argument = $null $ma.Name = "CloneVM_Task" $ar1 = New-Object VMware.Vim.MethodActionArgument $ar1.Value = $vm.Folder.ExtensionData.MoRef $ma.Argument += $ar1 $ar2 = New-Object VMware.Vim.MethodActionArgument $ar2.Value = $CloneVMName $ma.Argument += $ar2 $ar3 = New-Object VMware.Vim.MethodActionArgument $vmSpec = New-Object VMware.Vim.VirtualMachineCloneSpec $vmSpec.Location = New-Object VMware.Vim.VirtualMachineRelocateSpec #$vmSpec.Location.Datastore = $vm.ExtensionData.Datastore[0] #$vmSpec.Location.Datastore = (Get-Datastore -Name "*TEMPL*" -Server $VIServer).ExtensionData.MoRef $vmSpec.Location.Datastore = (Get-Datastore -Name $Destination.Name -Server $VIServer).ExtensionData.MoRef $vmSpec.Location.Pool = (Get-ResourcePool -VM $VM).ExtensionData.MoRef $vmSpec.Location.Folder = $Folder.ExtensionData.MoRef $vmSpec.Config = New-Object VMware.Vim.VirtualMachineConfigSpec $vmSpec.Template = $false $vmSpec.PowerOn = $false $ar3.Value = $vmSpec $ma.Argument += $ar3 <# # Run at 21:00 every day $dTScheduler = New-Object VMware.Vim.DailyTaskScheduler $dTScheduler.Hour = 14 $dTScheduler.Minute = 39 $dTScheduler.Interval = 1 #> $dTScheduler = New-Object VMware.Vim.OnceTaskScheduler $dTScheduler.runat = $CloneTime $tSpec = New-Object VMware.Vim.ScheduledTaskSpec $tSpec.Action = $ma $tSpec.Description = $CloneDescription $tSpec.Enabled = $TRUE $tSpec.Name = "AutoClone_" + $Request.ID + "_$VMName" $tSpec.Notification = $Request.Author.EMail $tSpec.Scheduler = $dTScheduler $stMgr = Get-View ScheduledTaskManager -Server $VIServer $stMgr.CreateScheduledTask($vm.ExtensionData.MoRef, $tSpec) } } catch { write-error "vCenter Clone Scheduled Task Creation failed" write-error $error[1] #Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov $Status = "Errored" exit } } } end { } }