Skip to content

Commit

Permalink
Version 2.0 - Proxy and Upgrade Support (#2)
Browse files Browse the repository at this point in the history
ADD:     Recipe::ProxyServer to handle installing proxy prerequisites and registration of the Proxy Server
ADD:     Recipe::ProxyRemove to handle proxy unregistration
ADD:     Resource::VeeamProxy
ADD:     Spec::VeeamProxy to test the custom_resource
UPDATE:  Rubocop.yml to set the TargetVersion to 2.3 and disable Style/FrozenStringLiteralComment
ADD:     Recipe::Upgrade to perform upgrades of Veeam components
ADD:     Resource::Upgrade
ADD:     Spec::Upgrade to test the custom_resource
Refactor Veeam::Helper library and methods.  Convert from Class to Module
UPDATE:  Resources to leverage DRY changes to Veeam::Helper
UPDATE:  Recipe::StandaloneComplete to include new VeeamUpgrade resource
UPDATE:  Resource::Prequisites to leverage a Windows Task for installation of SQL Express
ADD:     CHANGELOG.md
BUMP:    Metadata to version 2.0.0
  • Loading branch information
goodrum authored May 7, 2018
1 parent a1f3dce commit 2f40674
Show file tree
Hide file tree
Showing 31 changed files with 2,054 additions and 405 deletions.
40 changes: 40 additions & 0 deletions .kitchen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,43 @@ suites:
accept_eula: true
console:
accept_eula: true
- name: proxy_server
run_list:
- recipe[veeam::proxy_server]
verifier:
inspec_tests:
- test/inspec/9.5.0.711/console
attributes:
veeam:
version: '9.5'
console:
accept_eula: true
proxy:
register: false
- name: proxy_remove
run_list:
- recipe[veeam::proxy_remove]
verifier:
inspec_tests:
- test/inspec/9.5.0.711/console
attributes:
veeam:
version: '9.5'
console:
accept_eula: true
proxy:
register: false
- name: upgrade
run_list:
- recipe[veeam::server]
- recipe[veeam::upgrade]
verifier:
inspec_tests:
- test/inspec/9.5.0.711/server
attributes:
veeam:
version: '9.5.0.1536'
server:
accept_eula: true
console:
accept_eula: true
4 changes: 4 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
AllCops:
TargetRubyVersion: 2.3
Metrics/LineLength:
Max: 120
Style/FrozenStringLiteralComment:
Enabled: false
Style/TrailingCommaInLiteral:
# ChefAutomate will throw an error due to chages in protocol after
# Rubocop 0.39.0.
Expand Down
46 changes: 46 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Change log information for Veeam Cookbook

## Version 2.0
2018-05-04

Major update to the Veeam cookbook with full testing against Chef client 14.0.202. This update includes two new custom resources - VeeamProxy and VeeamUpgrade. Along with the new resources, a complete refactor of existing resources was completed to consolidate the helper methods into a single library.

### Included:
- Veeam Backup and Replication ProxyServer deployments
- Support for automatic Veeam Backup and Replication component Updates
- Refactor of existing Custom Resources and Helper Library

### Information on new resources:

* **VeeamProxy** - Configures a Windows server as either a VMware or HyperV Backup Proxy by connecting to the Veeam Backup and Replication server via the Veeam PowerShell toolkit. This resource will add a Veeam credential object if one does not exist and then register the server as a Proxy Type.
* **VeeamUpgrade** - The process to perform upgrades requires that the appropriate installation media is provided which contains the updates from Veeam. This cookbook will initiate an upgrade if the currently installed versions are less than the desired Build version as defined by the attribute `node['veeam']['build']`. When the installed version does not match the requested build version, the process will mount the ISO or extract the ZIP that contains the update and then perform an automatic upgrade of each service installed on the host.

### Major Updates:
- Veeam::Helper refactor
- SQL Express installation via Windows Scheduled task (resolves issues with remote builds on domain joined servers)


This cookbook is not officially supported by Veeam Software

## Version 1.0
2017-11-05

Initial release of the Veeam Cookbook including support for the new provisioning

### Included:
- Veeam Backup and Replication Server deployments
- Veeam Backup and Replication Catalog deployments
- Veeam Backup and Replication Console deployments
- Veeam Backup and Replication Prerequisite deployments
- Custom Resources and Helper Library


### Information on new resources:

* **VeeamPrerequisites** - Deploys all Veeam Prerequisite packages including SQL Tools, .NET 4.5, and SQL Express.
* **VeeamConsole** - Installs the Veeam Backup and Replication Console
* **VeeamCatalog** - Installs the Veeam Backup and Replication Catalog
* **VeeamServer** - Installs the Veeam Backup and Replication Server
* **VeeamExplorers** - Installs the Veeam Backup and Replication Explorers based on those available in the Installation Media.

This cookbook is not officially supported by Veeam Software
305 changes: 277 additions & 28 deletions README.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,9 @@ task integration: ['integration:kitchen:all']

# Default
task default: %w(style unit)

desc 'Run Local Development tests: Style, Foodcritic, Maintainers, Unit Tests, and Test-Kitchen'
task local: %w(style unit integration)

desc 'Autocorrect Rubocop Style errors'
task auto_correct: %w(style:ruby:auto_correct)
12 changes: 12 additions & 0 deletions attributes/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,15 @@
default['veeam']['installer']['package_url'] = nil # Local or custom URL location for ISO
default['veeam']['installer']['package_checksum'] = nil # Sha256 checksum of ISO
default['veeam']['license_url'] = nil
default['veeam']['installer']['update_url'] = node['veeam']['installer']['package_url'] # Local or custom URL location for ISO
default['veeam']['installer']['update_checksum'] = node['veeam']['installer']['package_checksum'] # Sha256 checksum of ISO

default['veeam']['build'] = if node['veeam']['installer']['update_url'].nil? && node['veeam']['installer']['package_url'].nil?
node['veeam']['version']
elsif node['veeam']['installer']['update_url'] == node['veeam']['installer']['package_url']
/(\d+.\d+.\d+.\d+)/.match(node['veeam']['installer']['package_url'].split('/')[-1]).captures[0]
else
/(\d+.\d+.\d+.\d+)/.match(node['veeam']['installer']['update_url'].split('/')[-1]).captures[0]
end
default['veeam']['reboot_on_upgrade'] = true
default['veeam']['upgrade']['keep_media'] = false
21 changes: 21 additions & 0 deletions attributes/proxy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#
# Cookbook Name:: veeam
# Attributes:: proxy
#
# Copyright (c) 2017 Exosphere Data LLC, All Rights Reserved.

default['veeam']['proxy']['vbr_server'] = nil
default['veeam']['proxy']['vbr_port'] = 9392
default['veeam']['proxy']['vbr_username'] = nil
default['veeam']['proxy']['vbr_password'] = nil

default['veeam']['proxy']['proxy_username'] = nil
default['veeam']['proxy']['proxy_password'] = nil

default['veeam']['proxy']['description'] = nil

default['veeam']['proxy']['max_tasks'] = 2
default['veeam']['proxy']['transport_mode'] = 'Auto'

default['veeam']['proxy']['use_ip_address'] = false
default['veeam']['proxy']['register'] = true
197 changes: 188 additions & 9 deletions libraries/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,23 @@
require 'chef/mixin/shell_out'

module Veeam
class Helper
extend Chef::Mixin::ShellOut

def self.check_os_version(node)
module Helper
def check_os_version(node)
# '6.1.' is the numeric platform_version for Windows 2008R2. If the node OS version is below that value, we must abort.
raise ArgumentError, 'Veeam Backup and Replication management requires a Windows 2008R2 or higher host!' if node['platform_version'].to_f < '6.1'.to_f
# If the kernel is not 64bit then raise an error, as we cannot proceed.
raise ArgumentError, 'Veeam Backup and Replication requires an x86_64 host and cannot be installed on this machine' unless node['kernel']['machine'] =~ /x86_64/
end

def self.find_package_url(version)
def find_package_url(version)
package_list(version)['package_url'] if package_list(version)
end

def self.find_package_checksum(version)
def find_package_checksum(version)
package_list(version)['package_checksum'] if package_list(version)
end

def self.package_list(version)
def package_list(version)
case version.to_s # to_s to make sure someone didn't pass us an int
when '9.0' then {
'package_url' => 'http://download2.veeam.com/VeeamBackup&Replication_9.0.0.902.iso',
Expand All @@ -52,10 +50,59 @@ def self.package_list(version)
'package_url' => 'http://download2.veeam.com/VeeamBackup&Replication_9.5.0.711.iso',
'package_checksum' => 'af3e3f6db9cb4a711256443894e6fb56da35d48c0b2c32d051960c52c5bc2f00'
}
when '9.5.0.711' then {
'package_url' => 'http://download2.veeam.com/VeeamBackup&Replication_9.5.0.711.iso',
'package_checksum' => 'af3e3f6db9cb4a711256443894e6fb56da35d48c0b2c32d051960c52c5bc2f00'
}
when '9.5.0.1038' then {
'package_url' => 'http://download2.veeam.com/VeeamBackup&Replication_9.5.0.1038.Update2.iso',
'package_checksum' => '180b142c1092c89001ba840fc97158cc9d3a37d6c7b25c93a311115b33454977'
}
when '9.5.0.1536' then {
'package_url' => 'http://download2.veeam.com/VeeamBackup&Replication_9.5.0.1536.Update3.iso',
'package_checksum' => '5020ef015e4d9ff7070d43cf477511a2b562d8044975552fd08f82bdcf556a43'
}
end
end

def self.prerequisites_list(version)
def find_update_url(version)
update_list(version)['update_url'] if update_list(version)
end

def find_update_checksum(version)
update_list(version)['update_checksum'] if update_list(version)
end

def update_list(version)
case version.to_s # to_s to make sure someone didn't pass us an int
when '9.0' then {
'update_url' => 'http://download2.veeam.com/VeeamBackup&Replication_9.0.0.902.iso',
'update_checksum' => '21f9d2c318911e668511990b8bbd2800141a7764cc97a8b78d4c2200c1225c88'
}
when '9.5' then {
'update_url' => 'http://download2.veeam.com/VeeamBackup&Replication_9.5.0.711.iso',
'update_checksum' => 'af3e3f6db9cb4a711256443894e6fb56da35d48c0b2c32d051960c52c5bc2f00'
}
when '9.5.0.711' then {
'update_url' => 'http://download2.veeam.com/VeeamBackup&Replication_9.5.0.711.iso',
'update_checksum' => 'af3e3f6db9cb4a711256443894e6fb56da35d48c0b2c32d051960c52c5bc2f00'
}
when '9.5.0.823' then {
'update_url' => 'https://download.veeam.com/VeeamBackup&Replication_9.5.0.823_Update1.zip',
'update_checksum' => 'c07bdfb3b90cc609d21ba94584ba19d8eaba16faa31f74ad80814ec9288df492'
}
when '9.5.0.1038' then {
'update_url' => 'http://download2.veeam.com/VeeamBackup&Replication_9.5.0.1038.Update2.zip',
'update_checksum' => 'd800bf5414f1bde95fba5fddbd86146c75a5a2414b967404792cc32841cb4ffb'
}
when '9.5.0.1536' then {
'update_url' => 'http://download2.veeam.com/VeeamBackup&Replication_9.5.0.1536.Update3.zip',
'update_checksum' => '38ed6a30aa271989477684fdfe7b98895affc19df7e1272ee646bb50a059addc'
}
end
end

def prerequisites_list(version)
case version.to_s # to_s to make sure someone didn't pass us an int
when '9.0' then {
'0' => { 'Microsoft System CLR Types for SQL Server 2012 (x64)' => 'SQLSysClrTypes.msi' },
Expand All @@ -70,7 +117,7 @@ def self.prerequisites_list(version)
end
end

def self.explorers_list(version)
def explorers_list(version)
case version.to_s # to_s to make sure someone didn't pass us an int
when '9.0' then {
'ActiveDirectory' => 'Veeam Explorer for Microsoft Active Directory',
Expand All @@ -88,5 +135,137 @@ def self.explorers_list(version)
}
end
end

def find_current_dotnet
installed_version = nil
installed_version_reg_key = registry_get_values('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full')
unless installed_version_reg_key.nil?
installed_version_reg_key.each do |key|
installed_version = key[:data] if key[:name] == 'Release'
end
end
installed_version.nil? ? 0 : installed_version
end

def validate_powershell_out(script, timeout: nil)
# This seemed like the DRYest way to handle the output handling from PowerShell.
cmd = powershell_out(script) if timeout.nil?
cmd = powershell_out(script, timeout: timeout) unless timeout.nil?
# Only return the output if there were no errors.
return cmd.stdout.chomp if cmd.stderr == '' || cmd.stderr.nil?
raise cmd.inspect if cmd.stderr != ''
end

def find_current_veeam_solutions(package_name)
cmd_str = <<-EOH
$program = '#{package_name}'
$x86 = (Get-ChildItem "HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall" | gp )
$x64 = (Get-ChildItem "HKLM:\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall" | gp )
$x86version = ($x86 | ?{$_.DisplayName -eq $program})
$x64version = ($x64 | ?{$_.DisplayName -eq $program})
if($x86version) {
return ($x86version.InstallLocation)
} elseif($x64version) {
return ($x64version.InstallLocation)
} else {
# Return nothing
}
EOH
output = validate_powershell_out(cmd_str)
raise ArgumentError, 'Unable to find the Veeam installation' unless output
output
end

def find_current_veeam_version(package_name)
veeam_package = find_current_veeam_solutions(package_name)
veeam_exe = case package_name
when /Console/
"#{veeam_package}\\Console\\veeam.backup.shell.exe"
when /Server/
"#{veeam_package}\\Packages\\VeeamDeploymentDll.dll"
when /Catalog/
"#{veeam_package}\\Backup Catalog\\VeeamDeploymentDll.dll"
else
raise "Unknown Package name: #{package_name}"
end
cmd_str = <<-EOH
$File = Get-Item -Path '#{veeam_exe}'
$File.VersionInfo.ProductVersion
EOH
output = validate_powershell_out(cmd_str)
output = nil if output == ''
output
end

def iso_installer(downloaded_file_name, new_resource)
remote_file downloaded_file_name do
source new_resource.package_url
checksum new_resource.package_checksum
use_conditional_get true # this should allow us to prevent duplicate downloads
action :create
end

# Mounting the Veeam backup ISO.
powershell_script 'Load Veeam media' do
code <<-EOH
Mount-DiskImage -ImagePath "#{downloaded_file_name}"
EOH
action :run
guard_interpreter :powershell_script
not_if "[boolean] (Get-DiskImage -ImagePath '#{downloaded_file_name}').DevicePath"
end
end

def extract_installer(downloaded_file_name, new_resource)
package_name = downloaded_file_name.split('\\').last
package_type = ::File.extname(package_name)
install_media_path = win_friendly_path(::File.join(::Chef::Config[:file_cache_path], "Veeam/#{package_name.gsub(package_type, '')}"))
update_path = win_friendly_path(::File.join(install_media_path, '/Updates'))

remote_file downloaded_file_name do
source new_resource.package_url
checksum new_resource.package_checksum
use_conditional_get true # this should allow us to prevent duplicate downloads
action :create
not_if { ::File.exist?(update_path) }
end

windows_zipfile win_friendly_path(::File.join(install_media_path, '/Updates')) do
source downloaded_file_name
action :unzip
not_if { ::File.exist?(update_path) }
end

install_media_path
end

def unmount_installer(downloaded_file_name)
# Unmount the Veeam backup ISO.
powershell_script 'Dismount Veeam media' do
code <<-EOH
Dismount-DiskImage -ImagePath "#{downloaded_file_name}"
EOH
action :run
guard_interpreter :powershell_script
only_if "[boolean] (Get-DiskImage -ImagePath '#{downloaded_file_name}').DevicePath"
end
end

def get_media_installer_location(downloaded_file_name)
# When downloading and mounting the ISO, we need to track back to the Drive Letter. This method will handle
# the look-up and keep the logic out of the main installation code.
Chef::Log.debug 'Searching for the Veeam installation media Drive Letter...'
cmd_str = <<-EOH
$DriveLetter = (Get-DiskImage -ImagePath '#{downloaded_file_name}' | Get-Volume).DriveLetter;
if ( [string]::IsNullOrEmpty($DriveLetter) ){ throw 'The ISO did not mount and we have no idea why.' }
return ( $DriveLetter +':\' )
EOH
output = validate_powershell_out(cmd_str)
raise ArgumentError, 'Unable to find the Veeam installation media' unless output
Chef::Log.debug "Found the Veeam installation media at Drive Letter [#{output}]"
output
end
end
end
Loading

0 comments on commit 2f40674

Please sign in to comment.