{"id":437,"date":"2010-06-13T22:52:22","date_gmt":"2010-06-13T21:52:22","guid":{"rendered":"http:\/\/www.amikkelsen.com\/?p=437"},"modified":"2010-06-22T20:52:58","modified_gmt":"2010-06-22T19:52:58","slug":"playing-with-the-vranger-4-5-vapi-powershell","status":"publish","type":"post","link":"https:\/\/www.amikkelsen.com\/?p=437","title":{"rendered":"Playing with the vRanger 4.5 vAPI (Powershell :-))"},"content":{"rendered":"<p>Since Vizioncore came out with vRanger 4.x, last year, I been working on porting the VBS script &#8220;<a href=\"http:\/\/www.amikkelsen.com\/?p=74\">vRanger Script version 2.0<\/a>&#8221; to Powershell.<br \/>\nDuring this time I have found several bugs\/missing functionality in the vAPI.<br \/>\nVizioncore have corrected the bugs with new releases of vRanger.<br \/>\nThe first vRanger version where all vAPI cmdlets worked in was version 4.2.3.<\/p>\n<p><strong>Porting the script from VBS presented me with a few challenges.<\/strong><\/p>\n<ul>\n<li>A reported error in the Get-Date cmdlet in Powershel 2.0.<br \/>\nHad to use a workaround.<\/li>\n<\/ul>\n<p><strong>A few words on the scrips functionality.<\/strong><\/p>\n<ul>\n<li>Control vRanger backups from vCenter (simple &#8211; one interface).<\/li>\n<li>Perform a FULL backup of DiskO of a VM.<\/li>\n<li>Perform a FULL backup of all disks of a VM.<\/li>\n<li>Backup a VM on a specific weekday.<\/li>\n<li>Control what week (Even\/Odd).<\/li>\n<li>Create a log file.<\/li>\n<li>Delete previous backup files from repository.<\/li>\n<li>Delete previous savepoints.<\/li>\n<li>Send an email when the jobs are completed &#8211; incl. succes\/errors.<\/li>\n<li>Offload the files to tape &#8211; TSM<\/li>\n<li>Send mail when TSM is finished offloading backup files.<\/li>\n<li>And many more&#8230;..<\/li>\n<\/ul>\n<p>When I started coding the script, I found, that if I used functions for all functionality the script was easier to read. Using functions also supplied me with the opportunity of reusing functions &#8211; less work :-).<\/p>\n<p>Some of the functions was created using examples posted and mailed by Scott Harold from <a href=\"http:\/\/www.quest.com\" target=\"_blank\">Quest<\/a> and <a href=\"http:\/\/www.thevesi.org\" target=\"_blank\">TheVesi.\/vEcoShell<\/a>.<\/p>\n<p><strong>Prerequirements<\/strong><\/p>\n<ul>\n<li><a href=\"http:\/\/technet.microsoft.com\/en-us\/scriptcenter\/powershell.aspx\" target=\"_blank\">Powershell 1.0 or 2.0 form Microsoft<\/a>.<\/li>\n<li><a href=\"http:\/\/www.vizioncore.com\/products\/vRangerPro\/index.php\" target=\"_blank\">Vizioncore vRanger 4.x<\/a><\/li>\n<li>A VMware vCenter server, a host and a few VMs.<\/li>\n<\/ul>\n<p><strong><span style=\"color: #ff0000;\">The script can be downloaded <a title=\"Download File\" href=\"http:\/\/www.amikkelsen.com\/?dl_id=26\" target=\"_self\">here<\/a>.<br \/>\n<\/span><\/strong><\/p>\n<p><strong>A quick overview of the functions.<\/strong><br \/>\nInclude the right PSSnapins<\/p>\n<pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\r\nfunction LoadSnapin{\r\n    Add-PSSnapin vRanger.API.PowerShell -ErrorAction SilentlyContinue\r\n    Add-PSSnapin vmware.VimAutomation.core -ErrorAction SilentlyContinue\r\n}\r\n\r\nLoadSnapin\r\n<\/pre>\n<p>Delete all previous savepoints &#8211; from the repository.<\/p>\n<pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\r\nfunction RemoveAllSavePoints{\r\n\tparam ($RASP_RepoName)\r\n\t$RASP_repoID = Get-Repository | where {$_.Name -eq $RASP_RepoName}\r\n\t$RASP_SPlist = Get-RepositorySavePoint -ID $RASP_repoID.Id\r\n\r\n\tforeach ($RASP_SP in $RASP_SPlist){\r\n\t\t#write $RASP_SP\r\n\t\tRemove-SavePoint -SavePointsToRemove $RASP_SP\r\n\t}\r\n}\r\n\r\nRemoveAllSavePoints &quot;Remote-Location&quot;\r\n<\/pre>\n<p>Is a backup job exist with the same name as the one to create &#8211; delete it.<\/p>\n<pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\r\nfunction Del-vRangerBackupJobs {\r\n\tparam ($delJobName)\r\n\t$delTemplateID = Get-JobTemplate | where {$_.JobName -eq $delJobName}\r\n\t# Verify that a BackupJob named XXX is present before deleting it.\r\n\tif ($delTemplateID){\r\n\t\t#write $delTemplateID.JobName\r\n\t\tRemove-JobTemplate -id $delTemplateID.Id\r\n\t}\r\n}\r\n\r\nDel-vRangerBackupJobs &quot;$Wednesday-Even&quot;\r\n<\/pre>\n<p>Create the list of VMs to exclude.<\/p>\n<pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\r\nfunction Filter-VMbyCF {\r\n    param ($customF, $val)\r\n    foreach ($vm in $vmlist) {\r\n        $vm.CustomFields | ForEach-Object {\r\n            $cf = $_\r\n            if ($_.Key -like $customF -and $_.Value -like $val){\r\n                    return $vm.name\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\nfunction New-vRangerExcludeList {\r\n    param ($exclude, $include)\r\n    $excludeArray = @()\r\n    $exclude | ForEach-Object {\r\n        if ($include -notcontains $_.Name){\r\n            $excludeArray += ($_.Config.Uuid)\r\n        }\r\n    }\r\n    return $excludeArray\r\n}\r\n\r\n$vmlist = Get-VM\r\n$tmplist = Get-Template\r\n$vmlist= $vmlist + $tmplist\r\n$vmFilter = Filter-VMbyCF $customField $CFValue\r\n$vmlistview = $vmlist | Get-View\r\n$excludeList = New-vRangerExcludeList -exclude $vmlistview -include $vmFilter\r\n<\/pre>\n<p>Create the new backup job.<\/p>\n<pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\r\nfunction New-vRangerBackupJob {\r\n\tparam ($customJobName, $customCFValue, $customFieldName, $customRepoName, $customExcludeList, $customEmail)\r\n        $jobDesc = &quot;This backup job is created by Logica for use in DR.  All VMs with a Custom Field labeled: $customFieldName with a value of: $customCFValue will be backed up&quot;\r\n        $jobEntity = Get-InventoryEntity -Type VirtualCenter\r\n\t$jobRepos = Get-Repository | where {$_.Name -eq $customRepoName}\r\n        $jobFlag = New-BackupFlag -CheckDestinationFreeSpace:$true -UseCompression:$true -PerformNetworkBackupOnFailure:$true\r\n\r\n\t# Check if all disks or just disk 0\r\n\tif ($customJobName -like &quot;*-All*&quot;){\r\n\t\t#write &quot;All - Disks&quot;\r\n\t\t#Add-BackupJobTemplate -JobName $customJobName -JobDescription $jobDesc -JobEntity $jobEntity -ExcludedVMList $customExcludeList -NotificationList $email -TargetRepository $jobRepos -Flags $jobFlag -NumberOfSavePoints 1 -SpaceSavingTechnologyTypeFlag None\r\n\t\tAdd-BackupJobTemplate -JobName $customJobName -JobDescription $jobDesc -JobEntity $jobEntity -ExcludedVMList $customExcludeList -NotificationList $customEmail -TargetRepository $jobRepos -Flags $jobFlag -NumberOfSavePoints 1 -SpaceSavingTechnologyTypeFlag None -SpaceSavingCountThreshold 6 -SpaceSavingPercentSizeThreshold 50\r\n\t}\r\n\telse{\r\n\t\t#write &quot;Only Disk 0&quot;\r\n\t\t#Add-BackupJobTemplate -JobName $customJobName -JobDescription $jobDesc -JobEntity $jobEntity -ExcludedVMList $customExcludeList -NotificationList $email -IncludedDiskList 0 -TargetRepository $jobRepos -Flags $jobFlag -NumberOfSavePoints 1 -SpaceSavingTechnologyTypeFlag None\r\n\t\tAdd-BackupJobTemplate -JobName $customJobName -JobDescription $jobDesc -JobEntity $jobEntity -ExcludedVMList $customExcludeList -NotificationList $customEmail -IncludedDiskList 0 -TargetRepository $jobRepos -Flags $jobFlag -NumberOfSavePoints 1 -SpaceSavingTechnologyTypeFlag None -SpaceSavingCountThreshold 6 -SpaceSavingPercentSizeThreshold 50\r\n\t}\r\n}\r\n\r\nNew-vRangerBackupJob &quot;Wednesday-Even&quot; &quot;Wednesday-Even&quot; &quot;Backup&quot; &quot;Remote-Location&quot; $excludeList &quot;to@email.com&quot;\r\n<\/pre>\n<p>Start the backup job.<\/p>\n<pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\r\nfunction Run-BackupJob{\r\n\tparam ($runJobName)\r\n\t$runTemplateID = Get-TemplateID $runJobName\r\n\tRun-JobsNow $runTemplateID\r\n}\r\n\r\nRun-BackupJob &quot;Wednesday-Even&quot;\r\n<\/pre>\n<p>Wait for the backup job to finish.<\/p>\n<pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\r\nfunction Get-TemplateID{\r\n\tparam($tmpJobName)\r\n\t$arrTemplate = get-jobtemplate | where {$_.JobName -eq $tmpJobName}\r\n\treturn $arrTemplate.ID\r\n}\r\n\r\nfunction WaitForJobToFinish{\r\n\tparam ($strWaitJob)\r\n\t$strCompleted = &quot;NotStarted&quot;\r\n        Start-Sleep -Seconds 300\t# 5 minutes\r\n\t$jobTemplates = get-JobTemplate | where {$_.JobName -eq $strWaitJob}\r\n\tforeach ($job in $jobTemplates){\r\n\t\tdo{\r\n\t\t\t$tasksinfo = get-job |where {$_.ParentJobTemplateID -eq $job.TemplateVersionID}\r\n\t\t\tforeach ($task in $tasksinfo){\r\n\t\t\t\tStart-Sleep -Seconds 300\t# 5 minutes\r\n\t\t\t\t$strCompleted = $task.JobState\r\n\r\n                # Make sure job is running - if not start it...\r\n                if ($task.JobState -eq $NULL -or $task.JobState -eq &quot;NotStarted&quot;){\r\n                    Run-BackupJob $strWaitJob\r\n                    Start-Sleep -Seconds 120\t# 2 minutes\r\n                }\r\n\t\t\t}\r\n\t\t}\r\n\t\twhile ($strCompleted -notmatch &quot;Completed&quot;)\r\n\t}\r\n}\r\n\r\nWaitForJobToFinish &quot;Wednesday-Even&quot;\r\n<\/pre>\n<p>Send TSM finished mail.<\/p>\n<pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\r\nfunction FuncMail {\r\n\t#param($strTo, $strFrom, $strSubject, $strBody, $smtpServer)\r\n\tparam($To, $From, $Subject, $Body, $smtpServer)\r\n\r\n\t$msg = new-object Net.Mail.MailMessage\r\n\t$smtp = new-object Net.Mail.SmtpClient($smtpServer)\r\n\t$msg.From = $From\r\n\t$msg.To.Add($To)\r\n\t$msg.Subject = $Subject\r\n\t$msg.IsBodyHtml = 1\r\n\t$msg.Body = $Body\r\n\t$smtp.Send($msg)\r\n}\r\n\r\nFuncMail -To &quot;to@email.com&quot; -From &quot;from@email.com&quot; -Subject &quot;vRanger Pro: TSM backup finished&quot; -Body &quot;Your Body&quot; -smtpServer &quot;your.mailserver.com&quot;\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Since Vizioncore came out with vRanger 4.x, last year, I been working on porting the VBS script &#8220;vRanger Script version 2.0&#8221; to Powershell. During this time I have found several bugs\/missing functionality in the vAPI. Vizioncore have corrected the bugs with new releases of vRanger. The first vRanger version where all vAPI cmdlets worked in\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.amikkelsen.com\/?p=437\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[224,21,18],"tags":[231,330,132,230],"class_list":["post-437","post","type-post","status-publish","format-standard","hentry","category-powercli-scripts","category-powershell","category-vranger","tag-cmdlet","tag-powershell","tag-vcenter","tag-vizioncore"],"_links":{"self":[{"href":"https:\/\/www.amikkelsen.com\/index.php?rest_route=\/wp\/v2\/posts\/437","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.amikkelsen.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.amikkelsen.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.amikkelsen.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.amikkelsen.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=437"}],"version-history":[{"count":21,"href":"https:\/\/www.amikkelsen.com\/index.php?rest_route=\/wp\/v2\/posts\/437\/revisions"}],"predecessor-version":[{"id":455,"href":"https:\/\/www.amikkelsen.com\/index.php?rest_route=\/wp\/v2\/posts\/437\/revisions\/455"}],"wp:attachment":[{"href":"https:\/\/www.amikkelsen.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=437"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.amikkelsen.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=437"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.amikkelsen.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=437"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}