diff --git a/.gitignore b/.gitignore index dd66a89..e079c64 100644 --- a/.gitignore +++ b/.gitignore @@ -14,5 +14,6 @@ bin/* .kitchen/ .kitchen.local.yml +.kitchen.local.*.yml .delivery/cli.toml diff --git a/.kitchen.yml b/.kitchen.yml index 033b36f..828f1a7 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -10,7 +10,7 @@ driver: provisioner: name: chef_zero data_bags_path: "../../data_bags/" - # You many wish to test your CHEF::Log. messages while using test-kitche. Change the below + # You many wish to test your CHEF::Log. messages while using test-kitchen. Change the below # value to the level of choice. For cleaner output, comment this option out. log_level: info # You may wish to disable always updating cookbooks in CI or other testing environments. diff --git a/README.md b/README.md index 29a4b15..2398c92 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,7 @@ The attribute `node['veeam']['version']` is used to evaluate the ISO download pa | **9.5.0.1038** | [VeeamBackup&Replication_9.5.0.1038.Update2.iso](http://download.veeam.com/VeeamBackup&Replication_9.5.0.1038.Update2.iso) | 180b142c1092c89001ba840fc97158cc9d3a37d6c7b25c93a311115b33454977 | | **9.5.0.1536** | [VeeamBackup&Replication_9.5.0.1536.Update3.iso](http://download.veeam.com/VeeamBackup&Replication_9.5.0.1536.Update3.iso) | 5020ef015e4d9ff7070d43cf477511a2b562d8044975552fd08f82bdcf556a43 | | **9.5.0.1922** | [VeeamBackup&Replication_9.5.0.1922.Update3a.iso](http://download.veeam.com/VeeamBackup&Replication_9.5.0.1922.Update3a.iso) | 9a6fa7d857396c058b2e65f20968de56f96bc293e0e8fd9f1a848c7d71534134 | +| **9.5.4.2615** | [VeeamBackup&Replication_9.5.4.2615.Update4.iso](http://download.veeam.com/VeeamBackup&Replication_9.5.4.2615.Update4.iso) | 8a594cec74059f9929ea765ac5e70a49da6fc93803b567cbb9d74fbb1a49a6cc | ### Veeam Backup and Replication Update Zip files @@ -193,6 +194,7 @@ The attribute `node['veeam']['build']` is used to evaluate the Zip download path | **Update 2** | [VeeamBackup&Replication_9.5.0.1038.Update2.zip](http://download.veeam.com/VeeamBackup&Replication_9.5.0.1038.Update2.zip) | d800bf5414f1bde95fba5fddbd86146c75a5a2414b967404792cc32841cb4ffb | | **Update 3** | [VeeamBackup&Replication_9.5.0.1536.Update3.zip](http://download.veeam.com/VeeamBackup&Replication_9.5.0.1536.Update3.zip) | 38ed6a30aa271989477684fdfe7b98895affc19df7e1272ee646bb50a059addc | | **Update 3a** | [VeeamBackup&Replication_9.5.0.1922.Update3a.zip](http://download.veeam.com/VeeamBackup&Replication_9.5.0.1922.Update3a.zip) | f6b3fc0963b09362c535ef49691c51d368266cc91d6833c80c70342161bb7123 | +| **Update 4** | [VeeamBackup&Replication_9.5.4.2615.Update4.iso](http://download.veeam.com/VeeamBackup&Replication_9.5.4.2615.Update4.iso) | 8a594cec74059f9929ea765ac5e70a49da6fc93803b567cbb9d74fbb1a49a6cc | ### Veeam Backup and Replication License file The server must be licensed to unlock the full potential of the application. The attribute `node['veeam']['server']['evaluation']` should be configured as `false`. To license, choose one of the below options. @@ -209,6 +211,8 @@ The server must be licensed to unlock the full potential of the application. Th ## Veeam Upgrade Procedures and Details 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. +> As of Update 4, the upgrade process has changed. The update to version 9.5.4+ will be automatically applied if the installer media leverages Update4. Due to the nature of the process, a reboot is required. The Automatic Reboot will occur at the end of the convergance unless the attribute `nde['veeam']['reboot_on_upgrade']` equals false + ### Configuring the Updates Updates are identified by passing one of the following to the attributes for the server: 1. `node['veeam']['installer']['update_url']` attribute should contain either the full installation ISO or the update ZIP link. The file name must include the full build name like such: @@ -221,6 +225,8 @@ Updates are identified by passing one of the following to the attributes for the - 9.5.0.711 (GA) - 9.5.0.1038 (Update2) - 9.5.0.1536 (Update3) + - 9.5.0.1922 (Update3a) + - 9.5.4.2615 (Update4) ### Upgrade Process and Warnings *Warning* @@ -231,7 +237,13 @@ If the automatic upgrade should be skipped then set the following attribute on t - `node['veeam']['reboot_on_upgrade']` = false ### Recipes that perform automatic upgrades +> As of Update 4, the upgrade process has changed. The update to version 9.5.4+ will be automatically applied if the installer media leverages Update4. Due to the nature of the process, a reboot is required. The Automatic Reboot will occur at the end of the convergance unless the attribute `nde['veeam']['reboot_on_upgrade']` equals false + Ongoing updates are automatically handled by the following included recipes: +- catalog +- console +- server_with_catalog +- server_with_console - standalone_complete - proxy_server - host_mgmt diff --git a/libraries/helper.rb b/libraries/helper.rb index 7637e11..0a4312d 100644 --- a/libraries/helper.rb +++ b/libraries/helper.rb @@ -22,6 +22,7 @@ # limitations under the License. require 'chef/mixin/shell_out' +require 'chef/util/path_helper' module Veeam module Helper @@ -66,6 +67,10 @@ def package_list(version) 'package_url' => 'https://download2.veeam.com/VeeamBackup&Replication_9.5.0.1922.Update3a.iso', 'package_checksum' => '9a6fa7d857396c058b2e65f20968de56f96bc293e0e8fd9f1a848c7d71534134' } + when '9.5.4.2615' then { + 'package_url' => 'https://download2.veeam.com/VeeamBackup&Replication_9.5.4.2615.Update4.iso', + 'package_checksum' => 'ecc27bbcf49104861566782701dca42375b324b4710e2fa79b5f8068c31c4494' + } end end @@ -107,6 +112,10 @@ def update_list(version) 'update_url' => 'http://download2.veeam.com/VeeamBackup&Replication_9.5.0.1922.Update3a.zip', 'update_checksum' => 'f6b3fc0963b09362c535ef49691c51d368266cc91d6833c80c70342161bb7123' } + when '9.5.4.2615' then { + 'package_url' => 'https://download2.veeam.com/VeeamBackup&Replication_9.5.4.2615.Update4.iso', + 'package_checksum' => 'ecc27bbcf49104861566782701dca42375b324b4710e2fa79b5f8068c31c4494' + } end end @@ -117,11 +126,26 @@ def prerequisites_list(version) '1' => { 'Microsoft SQL Server 2012 Management Objects (x64)' => 'SharedManagementObjects.msi' }, 'SQL' => { 'Microsoft SQL Server 2012 (64-bit)' => 'SQLEXPR_x64_ENU.exe' } } + when /9.0.0.\d+/ then { + '0' => { 'Microsoft System CLR Types for SQL Server 2012 (x64)' => 'SQLSysClrTypes.msi' }, + '1' => { 'Microsoft SQL Server 2012 Management Objects (x64)' => 'SharedManagementObjects.msi' }, + 'SQL' => { 'Microsoft SQL Server 2012 (64-bit)' => 'SQLEXPR_x64_ENU.exe' } + } when '9.5' then { '0' => { 'Microsoft System CLR Types for SQL Server 2014' => 'SQLSysClrTypes.msi' }, '1' => { 'Microsoft SQL Server 2014 Management Objects (x64)' => 'SharedManagementObjects.msi' }, 'SQL' => { 'Microsoft SQL Server 2012 (64-bit)' => 'SQLEXPR_x64_ENU.exe' } } + when /9.5.0.\d+/ then { + '0' => { 'Microsoft System CLR Types for SQL Server 2014' => 'SQLSysClrTypes.msi' }, + '1' => { 'Microsoft SQL Server 2014 Management Objects (x64)' => 'SharedManagementObjects.msi' }, + 'SQL' => { 'Microsoft SQL Server 2012 (64-bit)' => 'SQLEXPR_x64_ENU.exe' } + } + when /9.5.4.\d+/ then { + '0' => { 'Microsoft System CLR Types for SQL Server 2014' => 'SQLSysClrTypes.msi' }, + '1' => { 'Microsoft SQL Server 2014 Management Objects (x64)' => 'SharedManagementObjects.msi' }, + 'SQL' => { 'Microsoft SQL Server 2016 (64-bit)' => 'SQLEXPR_x64_ENU.exe' } + } end end @@ -135,11 +159,25 @@ def explorers_list(version) 'Oracle' => 'Veeam Explorer for Oracle' } when '9.5' then { - 'ActiveDirectory' => 'Veeam Explorer for Microsoft Active Directory', - 'SQL' => 'Veeam Explorer for Microsoft SQL Server', - 'Exchange' => 'Veeam Explorer for Microsoft Exchange', - 'SharePoint' => 'Veeam Explorer for Microsoft SharePoint', - 'Oracle' => 'Veeam Explorer for Oracle' + 'ActiveDirectory' => { name: 'Veeam Explorer for Microsoft Active Directory', version: '9.5.0.836' }, + 'SQL' => { name: 'Veeam Explorer for Microsoft SQL Server', version: '9.5.0.836' }, + 'Exchange' => { name: 'Veeam Explorer for Microsoft Exchange', version: '9.5.0.836' }, + 'SharePoint' => { name: 'Veeam Explorer for Microsoft SharePoint', version: '9.5.0.836' }, + 'Oracle' => { name: 'Veeam Explorer for Oracle', version: '9.5.0.836' } + } + when /9.5.4.\d+/ then { + 'ActiveDirectory' => { name: 'Veeam Explorer for Microsoft Active Directory', version: '9.6.4.1053' }, + 'SQL' => { name: 'Veeam Explorer for Microsoft SQL Server', version: '9.6.4.1053' }, + 'Exchange' => { name: 'Veeam Explorer for Microsoft Exchange', version: '9.6.4.1053' }, + 'SharePoint' => { name: 'Veeam Explorer for Microsoft SharePoint', version: '9.6.4.1053' }, + 'Oracle' => { name: 'Veeam Explorer for Oracle', version: '9.6.4.1053' } + } + when /9.5.0.\d+/ then { + 'ActiveDirectory' => { name: 'Veeam Explorer for Microsoft Active Directory', version: '9.5.0.836' }, + 'SQL' => { name: 'Veeam Explorer for Microsoft SQL Server', version: '9.5.0.836' }, + 'Exchange' => { name: 'Veeam Explorer for Microsoft Exchange', version: '9.5.0.836' }, + 'SharePoint' => { name: 'Veeam Explorer for Microsoft SharePoint', version: '9.5.0.836' }, + 'Oracle' => { name: 'Veeam Explorer for Oracle', version: '9.5.0.836' } } end end @@ -155,12 +193,12 @@ def find_current_dotnet installed_version.nil? ? 0 : installed_version end - def validate_powershell_out(script, timeout: nil) + def validate_powershell_out(script, timeout: nil, ignore_errors: false) # 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? + return cmd.stdout.chomp if cmd.stderr == '' || cmd.stderr.nil? || ignore_errors raise cmd.inspect if cmd.stderr != '' end @@ -192,7 +230,7 @@ def find_current_veeam_version(package_name) when /Console/ "#{veeam_package}\\Console\\veeam.backup.shell.exe" when /Server/ - "#{veeam_package}\\Packages\\VeeamDeploymentDll.dll" + "#{veeam_package}\\Backup\\Packages\\VeeamDeploymentDll.dll" when /Catalog/ "#{veeam_package}\\Backup Catalog\\VeeamDeploymentDll.dll" else @@ -202,7 +240,7 @@ def find_current_veeam_version(package_name) $File = Get-Item -Path '#{veeam_exe}' $File.VersionInfo.ProductVersion EOH - output = validate_powershell_out(cmd_str) + output = validate_powershell_out(cmd_str, ignore_errors: true) output = nil if output == '' output end @@ -227,10 +265,10 @@ def iso_installer(downloaded_file_name, new_resource) end def extract_installer(downloaded_file_name, new_resource) - package_name = downloaded_file_name.split('\\').last + 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')) + install_media_path = win_clean_path(::File.join(::Chef::Config[:file_cache_path], "Veeam/#{package_name.gsub(package_type, '')}")) + update_path = win_clean_path(::File.join(install_media_path, '/Updates')) remote_file downloaded_file_name do source new_resource.package_url @@ -240,7 +278,7 @@ def extract_installer(downloaded_file_name, new_resource) not_if { ::File.exist?(update_path) } end - windows_zipfile win_friendly_path(::File.join(install_media_path, '/Updates')) do + windows_zipfile win_clean_path(::File.join(install_media_path, '/Updates')) do source downloaded_file_name action :unzip not_if { ::File.exist?(update_path) } @@ -275,5 +313,9 @@ def get_media_installer_location(downloaded_file_name) Chef::Log.debug "Found the Veeam installation media at Drive Letter [#{output}]" output end + + def win_clean_path(path) + Chef::Util::PathHelper.cleanpath(path) + end end end diff --git a/metadata.rb b/metadata.rb index 2b92cc3..0a4bca3 100644 --- a/metadata.rb +++ b/metadata.rb @@ -4,7 +4,7 @@ license 'Apache-2.0' description 'Installs/Configures Veeam Backup and Recovery' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version '2.1.1' +version '3.0.0' chef_version '>= 12.5' if respond_to?(:chef_version) supports 'windows' diff --git a/recipes/catalog.rb b/recipes/catalog.rb index 99f54f3..f601b9f 100644 --- a/recipes/catalog.rb +++ b/recipes/catalog.rb @@ -15,7 +15,7 @@ veeam_prerequisites 'Install Veeam Prerequisites' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] install_sql false action :install end @@ -23,7 +23,7 @@ veeam_catalog 'Install Veeam Backup Catalog' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] install_dir node['veeam']['catalog']['install_dir'] vm_catalogpath node['veeam']['catalog']['vm_catalogpath'] vbrc_service_user node['veeam']['catalog']['vbrc_service_user'] @@ -32,3 +32,11 @@ keep_media node['veeam']['catalog']['keep_media'] action :install end + +veeam_upgrade node['veeam']['build'] do + package_url node['veeam']['installer']['update_url'] + package_checksum node['veeam']['installer']['update_checksum'] + keep_media node['veeam']['upgrade']['keep_media'] + auto_reboot node['veeam']['reboot_on_upgrade'] + action :install +end diff --git a/recipes/console.rb b/recipes/console.rb index 19fdafd..20ddd67 100644 --- a/recipes/console.rb +++ b/recipes/console.rb @@ -22,9 +22,17 @@ veeam_console 'Install Veeam Backup console' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] accept_eula node['veeam']['console']['accept_eula'] install_dir node['veeam']['console']['install_dir'] keep_media node['veeam']['console']['keep_media'] action :install end + +veeam_upgrade node['veeam']['build'] do + package_url node['veeam']['installer']['update_url'] + package_checksum node['veeam']['installer']['update_checksum'] + keep_media node['veeam']['upgrade']['keep_media'] + auto_reboot node['veeam']['reboot_on_upgrade'] + action :install +end diff --git a/recipes/host_mgmt.rb b/recipes/host_mgmt.rb index 1a57f7c..f9d6d45 100644 --- a/recipes/host_mgmt.rb +++ b/recipes/host_mgmt.rb @@ -18,7 +18,7 @@ veeam_prerequisites 'Install Veeam Prerequisites' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] install_sql false action :install end @@ -26,7 +26,7 @@ veeam_console 'Install Veeam Backup console' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] accept_eula node['veeam']['console']['accept_eula'] install_dir node['veeam']['console']['install_dir'] keep_media true diff --git a/recipes/prerequisites.rb b/recipes/prerequisites.rb new file mode 100644 index 0000000..50ea32a --- /dev/null +++ b/recipes/prerequisites.rb @@ -0,0 +1,21 @@ +# +# Cookbook Name:: veeam +# Recipe:: prerequisites +# +# Copyright (c) 2017 Exosphere Data LLC, All Rights Reserved. + +error_message = 'This recipe requires a Windows 2012 or higher host!' + +# If this host is not Windows, then abort +raise ArgumentError, error_message unless node['platform'] == 'windows' + +# If this host is older than Windows 2012, we should abort the process for an unsupported platform +raise ArgumentError, error_message if node['platform_version'].to_f < '6.2.9200'.to_f # '6.2.9200' is the numeric platform_version for Windows 2012 + +veeam_prerequisites 'Install Veeam Prerequisites' do + package_url node['veeam']['installer']['package_url'] + package_checksum node['veeam']['installer']['package_checksum'] + version node['veeam']['build'] + install_sql true + action :install +end diff --git a/recipes/proxy_server.rb b/recipes/proxy_server.rb index 9fb2cd0..df3e087 100644 --- a/recipes/proxy_server.rb +++ b/recipes/proxy_server.rb @@ -25,7 +25,7 @@ veeam_prerequisites 'Install Veeam Prerequisites' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] install_sql false action :install end @@ -33,7 +33,7 @@ veeam_console 'Install Veeam Backup console' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] accept_eula node['veeam']['console']['accept_eula'] install_dir node['veeam']['console']['install_dir'] keep_media true diff --git a/recipes/server.rb b/recipes/server.rb index 61b7098..f175729 100644 --- a/recipes/server.rb +++ b/recipes/server.rb @@ -15,7 +15,7 @@ veeam_prerequisites 'Install Veeam Prerequisites' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] install_sql true action :install end @@ -23,7 +23,7 @@ veeam_server 'Install Veeam Backup Server' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] accept_eula node['veeam']['server']['accept_eula'] evaluation node['veeam']['server']['evaluation'] install_dir node['veeam']['server']['install_dir'] @@ -33,3 +33,11 @@ keep_media node['veeam']['server']['keep_media'] action :install end + +veeam_upgrade node['veeam']['build'] do + package_url node['veeam']['installer']['update_url'] + package_checksum node['veeam']['installer']['update_checksum'] + keep_media node['veeam']['upgrade']['keep_media'] + auto_reboot node['veeam']['reboot_on_upgrade'] + action :install +end diff --git a/recipes/server_with_catalog.rb b/recipes/server_with_catalog.rb index c4a4120..91fdcf7 100644 --- a/recipes/server_with_catalog.rb +++ b/recipes/server_with_catalog.rb @@ -15,15 +15,29 @@ veeam_prerequisites 'Install Veeam Prerequisites' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] install_sql true action :install end +veeam_server 'Install Veeam Backup Server' do + package_url node['veeam']['installer']['package_url'] + package_checksum node['veeam']['installer']['package_checksum'] + version node['veeam']['build'] + accept_eula node['veeam']['server']['accept_eula'] + evaluation node['veeam']['server']['evaluation'] + install_dir node['veeam']['server']['install_dir'] + vbr_service_user node['veeam']['server']['vbr_service_user'] + vbr_service_password node['veeam']['server']['vbr_service_password'] + vbr_service_port node['veeam']['server']['vbr_service_port'] + keep_media node['veeam']['catalog']['keep_media'] || node['veeam']['server']['keep_media'] + action :install +end + veeam_catalog 'Install Veeam Backup Catalog' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] install_dir node['veeam']['catalog']['install_dir'] vm_catalogpath node['veeam']['catalog']['vm_catalogpath'] vbrc_service_user node['veeam']['catalog']['vbrc_service_user'] @@ -33,16 +47,10 @@ action :install end -veeam_server 'Install Veeam Backup Server' do - package_url node['veeam']['installer']['package_url'] - package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] - accept_eula node['veeam']['server']['accept_eula'] - evaluation node['veeam']['server']['evaluation'] - install_dir node['veeam']['server']['install_dir'] - vbr_service_user node['veeam']['server']['vbr_service_user'] - vbr_service_password node['veeam']['server']['vbr_service_password'] - vbr_service_port node['veeam']['server']['vbr_service_port'] - keep_media node['veeam']['catalog']['keep_media'] || node['veeam']['server']['keep_media'] +veeam_upgrade node['veeam']['build'] do + package_url node['veeam']['installer']['update_url'] + package_checksum node['veeam']['installer']['update_checksum'] + keep_media node['veeam']['upgrade']['keep_media'] || node['veeam']['console']['keep_media'] || node['veeam']['server']['keep_media'] + auto_reboot node['veeam']['reboot_on_upgrade'] action :install end diff --git a/recipes/server_with_console.rb b/recipes/server_with_console.rb index 2282cbf..d5c844d 100644 --- a/recipes/server_with_console.rb +++ b/recipes/server_with_console.rb @@ -15,25 +15,15 @@ veeam_prerequisites 'Install Veeam Prerequisites' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] install_sql true action :install end -veeam_console 'Install Veeam Backup Console' do - package_url node['veeam']['installer']['package_url'] - package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] - accept_eula node['veeam']['console']['accept_eula'] - install_dir node['veeam']['console']['install_dir'] - keep_media true - action :install -end - veeam_server 'Install Veeam Backup Server' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] accept_eula node['veeam']['server']['accept_eula'] evaluation node['veeam']['server']['evaluation'] install_dir node['veeam']['server']['install_dir'] @@ -44,11 +34,29 @@ action :install end +veeam_console 'Install Veeam Backup Console' do + package_url node['veeam']['installer']['package_url'] + package_checksum node['veeam']['installer']['package_checksum'] + version node['veeam']['build'] + accept_eula node['veeam']['console']['accept_eula'] + install_dir node['veeam']['console']['install_dir'] + keep_media true + action :install +end + veeam_explorer 'Install Veeam Backup Explorers' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] explorers node['veeam']['server']['explorers'] - keep_media node['veeam']['console']['keep_media'] || node['veeam']['server']['keep_media'] + keep_media true + action :install +end + +veeam_upgrade node['veeam']['build'] do + package_url node['veeam']['installer']['update_url'] + package_checksum node['veeam']['installer']['update_checksum'] + keep_media node['veeam']['upgrade']['keep_media'] || node['veeam']['console']['keep_media'] || node['veeam']['server']['keep_media'] + auto_reboot node['veeam']['reboot_on_upgrade'] action :install end diff --git a/recipes/standalone_complete.rb b/recipes/standalone_complete.rb index c0f1c7c..0b758f9 100644 --- a/recipes/standalone_complete.rb +++ b/recipes/standalone_complete.rb @@ -15,15 +15,30 @@ veeam_prerequisites 'Install Veeam Prerequisites' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] install_sql true action :install end +veeam_server 'Install Veeam Backup Server' do + package_url node['veeam']['installer']['package_url'] + package_checksum node['veeam']['installer']['package_checksum'] + version node['veeam']['build'] + accept_eula node['veeam']['server']['accept_eula'] + evaluation node['veeam']['server']['evaluation'] + install_dir node['veeam']['server']['install_dir'] + vbr_service_user node['veeam']['server']['vbr_service_user'] + vbr_service_password node['veeam']['server']['vbr_service_password'] + vbr_service_port node['veeam']['server']['vbr_service_port'] + vbr_check_updates true + keep_media true + action :install +end + veeam_catalog 'Install Veeam Backup Catalog' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] install_dir node['veeam']['catalog']['install_dir'] vm_catalogpath node['veeam']['catalog']['vm_catalogpath'] vbrc_service_user node['veeam']['catalog']['vbrc_service_user'] @@ -36,32 +51,17 @@ veeam_console 'Install Veeam Backup Console' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] accept_eula node['veeam']['console']['accept_eula'] install_dir node['veeam']['console']['install_dir'] keep_media node['veeam']['catalog']['keep_media'] || node['veeam']['console']['keep_media'] || node['veeam']['server']['keep_media'] action :install end -veeam_server 'Install Veeam Backup Server' do - package_url node['veeam']['installer']['package_url'] - package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] - accept_eula node['veeam']['server']['accept_eula'] - evaluation node['veeam']['server']['evaluation'] - install_dir node['veeam']['server']['install_dir'] - vbr_service_user node['veeam']['server']['vbr_service_user'] - vbr_service_password node['veeam']['server']['vbr_service_password'] - vbr_service_port node['veeam']['server']['vbr_service_port'] - vbr_check_updates true - keep_media true - action :install -end - veeam_explorer 'Install Veeam Backup Explorers' do package_url node['veeam']['installer']['package_url'] package_checksum node['veeam']['installer']['package_checksum'] - version node['veeam']['version'] + version node['veeam']['build'] explorers node['veeam']['server']['explorers'] keep_media node['veeam']['console']['keep_media'] || node['veeam']['server']['keep_media'] action :install diff --git a/resources/catalog.rb b/resources/catalog.rb index 91e5c09..7b03ba4 100644 --- a/resources/catalog.rb +++ b/resources/catalog.rb @@ -47,14 +47,25 @@ # We will use the Windows Helper 'is_package_installed?' to see if the Catalog Server is installed. If it is installed, then # we should report no change back. By returning 'false', Chef will report that the resource is up-to-date. - return false if is_package_installed?('Veeam Backup Catalog') + if is_package_installed?('Veeam Backup Catalog') + installed_version = installed_packages['Veeam Backup Catalog'][:version] + + # => If the build version and the installed version match then return up-to-date + return false if Gem::Version.new(new_resource.version) == Gem::Version.new(installed_version) + + # => Previous versions are upgraded through update files and therefore, this is up-to-date + return false if Gem::Version.new(new_resource.version) <= Gem::Version.new('9.5.3.0') + + # => An Upgrade is available and should be started + Chef::Log.info('New Catalog Upgrade is available') + end # We need to verify that .NET Framework 4.5.2 or higher has been installed on the machine raise 'The Veeam Backup and Recovery Server requires that Microsoft .NET Framework 4.5.2 or higher be installed. Please install the Veeam pre-requisites' if find_current_dotnet < 379893 raise ArgumentError, 'The VBRC service password must be set if a username is supplied' if new_resource.vbrc_service_user && new_resource.vbrc_service_password.nil? - package_save_dir = win_friendly_path(::File.join(::Chef::Config[:file_cache_path], 'package')) + package_save_dir = win_clean_path(::File.join(::Chef::Config[:file_cache_path], 'package')) # This will only create the directory if it does not exist which is likely the case if we have # never performed a remote_file install. @@ -79,7 +90,7 @@ Chef::Log.debug('Downloading Veeam Backup and Recovery software via URL') package_name = new_resource.package_url.split('/').last - installer_file_name = win_friendly_path(::File.join(package_save_dir, package_name)) + installer_file_name = win_clean_path(::File.join(package_save_dir, package_name)) iso_installer(installer_file_name, new_resource) ruby_block 'Install the Backup Catalog application' do @@ -123,6 +134,7 @@ def perform_catalog_install(install_media_path) xtra_arguments.concat(" VBRC_SERVICE_USER=\"#{new_resource.vbrc_service_user}\" ") unless new_resource.vbrc_service_user.nil? xtra_arguments.concat(" VBRC_SERVICE_PASSWORD=\"#{new_resource.vbrc_service_password}\" ") unless new_resource.vbrc_service_password.nil? xtra_arguments.concat(" VBRC_SERVICE_PORT=\"#{new_resource.vbrc_service_port}\" ") unless new_resource.vbrc_service_port.nil? + xtra_arguments.concat(' ACCEPT_THIRDPARTY_LICENSES="1" ') cmd_str = <<-EOH $veeam_backup_catalog_installer = ( "#{install_media_path}\\Catalog\\VeeamBackupCatalog64.msi") diff --git a/resources/console.rb b/resources/console.rb index b6b8523..7e3832d 100644 --- a/resources/console.rb +++ b/resources/console.rb @@ -1,3 +1,4 @@ + # Cookbook Name:: veeam # Resource:: console # @@ -44,7 +45,18 @@ # We will use the Windows Helper 'is_package_installed?' to see if the Console is installed. If it is installed, then # we should report no change back. By returning 'false', Chef will report that the resource is up-to-date. - return false if is_package_installed?('Veeam Backup & Replication Console') + if is_package_installed?('Veeam Backup & Replication Console') + installed_version = installed_packages['Veeam Backup & Replication Console'][:version] + + # => If the build version and the installed version match then return up-to-date + return false if Gem::Version.new(new_resource.version) == Gem::Version.new(installed_version) + + # => Previous versions are upgraded through update files and therefore, this is up-to-date + return false if Gem::Version.new(new_resource.version) <= Gem::Version.new('9.5.3.0') + + # => An Upgrade is available and should be started + Chef::Log.info('New Console Upgrade is available') + end # We need to verify that .NET Framework 4.5.2 or higher has been installed on the machine raise 'The Veeam Backup and Recovery Server requires that Microsoft .NET Framework 4.5.2 or higher be installed. Please install the Veeam pre-requisites' if find_current_dotnet < 379893 @@ -52,7 +64,7 @@ # The EULA must be explicitly accepted. raise ArgumentError, 'The Veeam Backup and Recovery EULA must be accepted. Please set the node attribute [\'veeam\'][\'console\'][\'accept_eula\'] to \'true\' ' if new_resource.accept_eula.nil? || new_resource.accept_eula == false - package_save_dir = win_friendly_path(::File.join(::Chef::Config[:file_cache_path], 'package')) + package_save_dir = win_clean_path(::File.join(::Chef::Config[:file_cache_path], 'package')) # This will only create the directory if it does not exist which is likely the case if we have # never performed a remote_file install. @@ -77,7 +89,7 @@ Chef::Log.debug('Downloading Veeam Backup and Recovery software via URL') package_name = new_resource.package_url.split('/').last - installer_file_name = win_friendly_path(::File.join(package_save_dir, package_name)) + installer_file_name = win_clean_path(::File.join(package_save_dir, package_name)) iso_installer(installer_file_name, new_resource) ruby_block 'Install the Backup console application' do @@ -118,6 +130,7 @@ def perform_console_install(install_media_path) xtra_arguments = '' xtra_arguments.concat(" ACCEPTEULA=\"#{new_resource.accept_eula ? 'YES' : 'NO'}\" ") unless new_resource.accept_eula.nil? xtra_arguments.concat(" INSTALLDIR=\"#{new_resource.install_dir} \" ") unless new_resource.install_dir.nil? + xtra_arguments.concat(' ACCEPT_THIRDPARTY_LICENSES="1" ') cmd_str = <<-EOH $veeam_backup_console_installer = ( "#{install_media_path}\\Backup\\Shell.x64.msi") diff --git a/resources/explorer.rb b/resources/explorer.rb index 6dbe20e..f920e9b 100644 --- a/resources/explorer.rb +++ b/resources/explorer.rb @@ -57,17 +57,26 @@ # Determine if all of the Veeam Explorers are installed and if so, then skip the processing. installed_explorers = [] - explorers_list = explorers_list(new_resource.version) + explorers_hash = explorers_list(new_resource.version) new_resource.explorers.each do |explorer| - installed_explorers.push(explorer) if is_package_installed?(explorers_list[explorer]) + package_name = explorers_hash[explorer][:name] + package_version = explorers_hash[explorer][:version] + next unless is_package_installed?(package_name) + installed_version = installed_packages[package_name][:version] + if installed_version == package_version + installed_explorers.push(explorer) + else + Chef::Log.info("The package #{package_name} is installed with version #{installed_version} but should be upgraded to #{package_version}") + end end + # return false # Compare the required Explorers with those installed. If all are installed, then # we should report no change back. By returning 'false', Chef will report that the resource is up-to-date. return false if (new_resource.explorers - installed_explorers).empty? - package_save_dir = win_friendly_path(::File.join(::Chef::Config[:file_cache_path], 'package')) + package_save_dir = win_clean_path(::File.join(::Chef::Config[:file_cache_path], 'package')) # This will only create the directory if it does not exist which is likely the case if we have # never performed a remote_file install. @@ -81,7 +90,7 @@ Chef::Log.debug('Downloading Veeam Backup and Replication software via URL') package_name = new_resource.package_url.split('/').last - installer_file_name = win_friendly_path(::File.join(package_save_dir, package_name)) + installer_file_name = win_clean_path(::File.join(package_save_dir, package_name)) iso_installer(installer_file_name, new_resource) # We need to delay the evaluation of this so that we can properly get the value during run time. @@ -91,14 +100,15 @@ veeam_explorer_root = "#{install_media_path}\\Explorers" new_resource.explorers.each do |explorer| - Chef::Log.debug "Installing Veeam Explorer for #{explorers_list[explorer]}... begin" - windows_package explorers_list[explorer] do + Chef::Log.debug "Installing Veeam Explorer for #{explorers_hash[explorer][:name]}... begin" + windows_package explorers_hash[explorer][:name] do provider Chef::Provider::Package::Windows source "#{veeam_explorer_root}\\VeeamExplorerFor#{explorer}.msi" + options 'ACCEPT_THIRDPARTY_LICENSES="1" ACCEPT_EULA="1"' installer_type :msi action :install end - Chef::Log.debug "Installing Veeam Explorer for #{explorers_list[explorer]}... success" + Chef::Log.debug "Installing Veeam Explorer for #{explorers_hash[explorer][:name]}... success" end end end diff --git a/resources/prerequisites.rb b/resources/prerequisites.rb index b16dd6b..9fdfe5e 100644 --- a/resources/prerequisites.rb +++ b/resources/prerequisites.rb @@ -49,24 +49,27 @@ # Halt this process now. There is no URL for the package. raise ArgumentError, 'You must provide a package URL or choose a valid version' unless new_resource.package_url - # Determine if all of the Veeam pre-requisites are installed and if so, then skip the processing. - prerequisites_required = [] - installed_prerequisites = [] - prerequisites_hash = prerequisites_list(new_resource.version) - - prerequisites_hash.each do |item, prerequisites| - package_name = prerequisites.map { |k, _v| k }.join(',') - unless item == 'SQL' && new_resource.install_sql == false - prerequisites_required.push(package_name) - installed_prerequisites.push(package_name) if is_package_installed?(package_name) + base_version = /(\d+.\d+)/.match(new_resource.version).captures[0] + [base_version, new_resource.version].each do |test_version| + # Determine if all of the Veeam pre-requisites are installed and if so, then skip the processing. + prerequisites_required = [] + installed_prerequisites = [] + prerequisites_hash = prerequisites_list(test_version) + + prerequisites_hash.each do |item, prerequisites| + package_name = prerequisites.map { |k, _v| k }.join(',') + unless item == 'SQL' && new_resource.install_sql == false + prerequisites_required.push(package_name) + installed_prerequisites.push(package_name) if is_package_installed?(package_name) + end end - end - # Compare the required Prerequisites with those installed. If all are installed, then - # we should report no change back. By returning 'false', Chef will report that the resource is up-to-date. - return false if (prerequisites_required - installed_prerequisites).empty? && find_current_dotnet >= 379893 + # Compare the required Prerequisites with those installed. If all are installed, then + # we should report no change back. By returning 'false', Chef will report that the resource is up-to-date. + return false if (prerequisites_required - installed_prerequisites).empty? && find_current_dotnet >= 379893 + end - package_save_dir = win_friendly_path(::File.join(::Chef::Config[:file_cache_path], 'package')) + package_save_dir = win_clean_path(::File.join(::Chef::Config[:file_cache_path], 'package')) # This will only create the directory if it does not exist which is likely the case if we have # never performed a remote_file install. @@ -80,7 +83,7 @@ Chef::Log.debug('Downloading Veeam Backup and Recovery software via URL') package_name = new_resource.package_url.split('/').last - installer_file_name = win_friendly_path(::File.join(package_save_dir, package_name)) + installer_file_name = win_clean_path(::File.join(package_save_dir, package_name)) iso_installer(installer_file_name, new_resource) install_dotnet(installer_file_name) @@ -153,9 +156,9 @@ def install_sql_tools(downloaded_file_name) def install_sql_express(downloaded_file_name) installed_version_reg_key = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\\MSSQL11.SQLEXPRESS\MSSQLServer\CurrentVersion' return 'Already Installed' if registry_key_exists?(installed_version_reg_key, :machine) - config_file_path = win_friendly_path(::File.join(::Chef::Config[:file_cache_path], 'ConfigurationFile.ini')) - output_file = win_friendly_path(::File.join(Chef::Config[:file_cache_path], 'sql_install.log')) - sql_build_script = win_friendly_path(::File.join(Chef::Config[:file_cache_path], 'sql_build_script.ps1')) + config_file_path = win_clean_path(::File.join(::Chef::Config[:file_cache_path], 'ConfigurationFile.ini')) + output_file = win_clean_path(::File.join(Chef::Config[:file_cache_path], 'sql_install.log')) + sql_build_script = win_clean_path(::File.join(Chef::Config[:file_cache_path], 'sql_build_script.ps1')) sql_sys_admin_list = "NT AUTHORITY\\SYSTEM\" \"#{node['hostname']}\\#{ENV['USERNAME']}" sql_sys_admin_list = node['veeam']['server']['vbr_service_user'] if node['veeam']['server']['vbr_service_user'] @@ -173,14 +176,13 @@ def install_sql_express(downloaded_file_name) ruby_block 'Install the SQL Express' do block do install_media_path = get_media_installer_location(downloaded_file_name) - sql_installer = "#{install_media_path}\\Redistr\\x64\\SQLEXPR_x64_ENU.exe" - template sql_build_script do backup false sensitive true source ::File.join('sql_server', 'sql_build_script.ps1.erb') variables( - sql_build_command: "#{sql_installer} /q /ConfigurationFile=#{config_file_path}", + sql_install_media: "#{install_media_path}\\Redistr\\x64", + sql_build_command: "/q /ConfigurationFile=#{config_file_path}", outputFilePath: output_file ) action :create diff --git a/resources/server.rb b/resources/server.rb index 64420e7..a9b2c82 100644 --- a/resources/server.rb +++ b/resources/server.rb @@ -53,6 +53,7 @@ property :version, String, required: true property :keep_media, [TrueClass, FalseClass], default: false +property :auto_reboot, [TrueClass, FalseClass], default: true # We need to include the windows helpers to keep things dry ::Chef::Provider.send(:include, Windows::Helper) @@ -63,7 +64,18 @@ # We will use the Windows Helper 'is_package_installed?' to see if the Server is installed. If it is installed, then # we should report no change back. By returning 'false', Chef will report that the resource is up-to-date. - return false if is_package_installed?('Veeam Backup & Replication Server') + if is_package_installed?('Veeam Backup & Replication Server') + installed_version = installed_packages['Veeam Backup & Replication Server'][:version] + + # => If the build version and the installed version match then return up-to-date + return false if Gem::Version.new(new_resource.version) == Gem::Version.new(installed_version) + + # => Previous versions are upgraded through update files and therefore, this is up-to-date + return false if Gem::Version.new(new_resource.version) <= Gem::Version.new('9.5.3.0') + + # => An Upgrade is available and should be started + Chef::Log.info('New Server Upgrade is available') + end # We need to verify that .NET Framework 4.5.2 or higher has been installed on the machine raise 'The Veeam Backup and Replication Server requires that Microsoft .NET Framework 4.5.2 or higher be installed. Please install the Veeam pre-requisites' if find_current_dotnet < 379893 @@ -71,7 +83,7 @@ raise ArgumentError, 'The Veeam Backup and Replication EULA must be accepted. Please set the node attribute [\'veeam\'][\'server\'][\'accept_eula\'] to \'true\' ' unless new_resource.accept_eula == true raise ArgumentError, 'The VBR service password must be set if a username is supplied' if new_resource.vbr_service_user && new_resource.vbr_service_password.nil? - package_save_dir = win_friendly_path(::File.join(::Chef::Config[:file_cache_path], 'package')) + package_save_dir = win_clean_path(::File.join(::Chef::Config[:file_cache_path], 'package')) # This will only create the directory if it does not exist which is likely the case if we have # never performed a remote_file install. @@ -96,7 +108,7 @@ Chef::Log.debug('Downloading Veeam Backup and Replication software via URL') package_name = new_resource.package_url.split('/').last - installer_file_name = win_friendly_path(::File.join(package_save_dir, package_name)) + installer_file_name = win_clean_path(::File.join(package_save_dir, package_name)) iso_installer(installer_file_name, new_resource) new_resource.vbr_license_file = find_vbr_license unless new_resource.evaluation @@ -130,7 +142,7 @@ def whyrun_supported? end def find_vbr_license - license_file = win_friendly_path(::File.join(Chef::Config[:file_cache_path], 'Veeam-license-file.lic')) + license_file = win_clean_path(::File.join(Chef::Config[:file_cache_path], 'Veeam-license-file.lic')) if node['veeam']['license_url'] remote_file license_file do @@ -184,16 +196,29 @@ def perform_server_install(install_media_path) xtra_arguments.concat(" VBR_SQLSERVER_USERNAME=\"#{new_resource.vbr_sqlserver_username}\" ") unless new_resource.vbr_sqlserver_username.nil? xtra_arguments.concat(" VBR_SQLSERVER_PASSWORD=\"#{new_resource.vbr_sqlserver_password}\" ") unless new_resource.vbr_sqlserver_password.nil? xtra_arguments.concat(" PF_AD_NFSDATASTORE=\"#{new_resource.pf_ad_nfsdatastore}\" ") unless new_resource.pf_ad_nfsdatastore.nil? + xtra_arguments.concat(' ACCEPT_THIRDPARTY_LICENSES="1" ') cmd_str = <<-EOH $veeam_backup_server_installer = ( "#{install_media_path}\\Backup\\Server.x64.msi") Write-Host (' /qn /i ' + $veeam_backup_server_installer + ' #{xtra_arguments}') - $output = (Start-Process -FilePath "msiexec.exe" -ArgumentList $(' /qn /i ' + $veeam_backup_server_installer + ' #{xtra_arguments}') -Wait -Passthru -ErrorAction Stop) - if ( $output.ExitCode -ne 0){ - throw ("The install failed with ExitCode [{0}]. The package is {1}" -f $output.ExitCode, $veeam_backup_server_installer ) - } + $log_file = "veeam_installer.log" + $output = (Start-Process -FilePath "msiexec.exe" -ArgumentList $(' /qn /norestart /i ' + $veeam_backup_server_installer + ' #{xtra_arguments} /log #{::Chef::Config[:file_cache_path]}\\' + $log_file) -Wait -Passthru -ErrorAction Stop) + switch ( $output.ExitCode){ + 0 { Write-Host "Veeam Install Completed Successfully" } + 1641 { Write-Host "Need Reboot"} + 3010 { Write-Host "Need Reboot"} + default { + throw ("The updates failed with ExitCode [{0}]. The package is {1}" -f $output.ExitCode, $veeam_backup_server_installer ) + } + } EOH validate_powershell_out(cmd_str) Chef::Log.debug 'Installing Veeam Backup server service... success' + + reboot 'Required Reboot after Veeam Installation or Upgrade' do + action :request_reboot + only_if { reboot_pending? } + only_if { new_resource.auto_reboot } + end end end diff --git a/resources/upgrade.rb b/resources/upgrade.rb index a2b5b1b..6b6c4ee 100644 --- a/resources/upgrade.rb +++ b/resources/upgrade.rb @@ -63,7 +63,7 @@ # => We need to determine the actual build of installed Veeam Software. Since there are three main packages # => we will need to iterate through their possible locations. current_build = nil - ['Veeam Backup & Replication Console', 'Veeam Backup & Replication Server', 'Veeam Backup & Replication Catalog'].each do |package| + ['Veeam Backup & Replication Console', 'Veeam Backup & Replication Server', 'Veeam Backup Catalog'].each do |package| current_build = find_current_veeam_version(package) break unless current_build.nil? end @@ -79,7 +79,7 @@ # We need to verify that .NET Framework 4.5.2 or higher has been installed on the machine raise 'The Veeam Backup and Replication Server requires that Microsoft .NET Framework 4.5.2 or higher be installed. Please install the Veeam pre-requisites' if find_current_dotnet < 379893 - package_save_dir = win_friendly_path(::File.join(::Chef::Config[:file_cache_path], 'package')) + package_save_dir = win_clean_path(::File.join(::Chef::Config[:file_cache_path], 'package')) # This will only create the directory if it does not exist which is likely the case if we have # never performed a remote_file install. @@ -97,7 +97,7 @@ package_name = package_name.gsub(special_char, '_') end package_type = ::File.extname(package_name) - installer_file_name = win_friendly_path(::File.join(package_save_dir, package_name)) + installer_file_name = win_clean_path(::File.join(package_save_dir, package_name)) install_media_path = if package_type == '.iso' iso_installer(installer_file_name, new_resource) diff --git a/spec/unit/lwrps/veeam_catalog_spec.rb b/spec/unit/lwrps/veeam_catalog_spec.rb index e8f1ff7..3906a5c 100644 --- a/spec/unit/lwrps/veeam_catalog_spec.rb +++ b/spec/unit/lwrps/veeam_catalog_spec.rb @@ -34,8 +34,8 @@ end let(:node) { runner.node } let(:chef_run) { runner.converge(described_recipe) } - let(:package_save_dir) { win_friendly_path(::File.join(Chef::Config[:file_cache_path], 'package')) } - let(:downloaded_file_name) { win_friendly_path(::File.join(package_save_dir, 'VeeamBackup&Replication_9.5.0.711.iso')) } + let(:package_save_dir) { win_clean_path(::File.join(Chef::Config[:file_cache_path], 'package')) } + let(:downloaded_file_name) { win_clean_path(::File.join(package_save_dir, 'VeeamBackup&Replication_9.5.0.711.iso')) } it 'converges successfully' do expect(chef_run).to install_veeam_prerequisites('Install Veeam Prerequisites') diff --git a/spec/unit/lwrps/veeam_console_spec.rb b/spec/unit/lwrps/veeam_console_spec.rb index 112f435..0ba8e0b 100644 --- a/spec/unit/lwrps/veeam_console_spec.rb +++ b/spec/unit/lwrps/veeam_console_spec.rb @@ -35,8 +35,8 @@ end let(:node) { runner.node } let(:chef_run) { runner.converge(described_recipe) } - let(:package_save_dir) { win_friendly_path(::File.join(Chef::Config[:file_cache_path], 'package')) } - let(:downloaded_file_name) { win_friendly_path(::File.join(package_save_dir, 'VeeamBackup&Replication_9.5.0.711.iso')) } + let(:package_save_dir) { win_clean_path(::File.join(Chef::Config[:file_cache_path], 'package')) } + let(:downloaded_file_name) { win_clean_path(::File.join(package_save_dir, 'VeeamBackup&Replication_9.5.0.711.iso')) } it 'converges successfully' do expect(chef_run).to install_veeam_prerequisites('Install Veeam Prerequisites') diff --git a/spec/unit/lwrps/veeam_explorer_spec.rb b/spec/unit/lwrps/veeam_explorer_spec.rb index a1d26de..674e4bd 100644 --- a/spec/unit/lwrps/veeam_explorer_spec.rb +++ b/spec/unit/lwrps/veeam_explorer_spec.rb @@ -46,8 +46,8 @@ end let(:node) { runner.node } let(:chef_run) { runner.converge(described_recipe) } - let(:package_save_dir) { win_friendly_path(::File.join(Chef::Config[:file_cache_path], 'package')) } - let(:downloaded_file_name) { win_friendly_path(::File.join(package_save_dir, 'VeeamBackup&Replication_9.5.0.711.iso')) } + let(:package_save_dir) { win_clean_path(::File.join(Chef::Config[:file_cache_path], 'package')) } + let(:downloaded_file_name) { win_clean_path(::File.join(package_save_dir, 'VeeamBackup&Replication_9.5.0.711.iso')) } it 'converges successfully' do expect { chef_run }.not_to raise_error @@ -62,7 +62,6 @@ expect(chef_run).to create_remote_file(downloaded_file_name) expect(chef_run).to run_powershell_script('Load Veeam media') expect(chef_run).to run_ruby_block('Install Veeam Explorers') - expect(chef_run).to delete_file(downloaded_file_name) end it 'should RAISE an error if Veeam Server not installed' do allow_any_instance_of(Chef::Provider).to receive(:is_package_installed?).with('Veeam Backup & Replication Server').and_return(false) diff --git a/spec/unit/lwrps/veeam_prerequisites_spec.rb b/spec/unit/lwrps/veeam_prerequisites_spec.rb index 9109c8d..ba08d40 100644 --- a/spec/unit/lwrps/veeam_prerequisites_spec.rb +++ b/spec/unit/lwrps/veeam_prerequisites_spec.rb @@ -30,8 +30,8 @@ end let(:node) { runner.node } let(:chef_run) { runner.converge(described_recipe) } - let(:package_save_dir) { win_friendly_path(::File.join(Chef::Config[:file_cache_path], 'package')) } - let(:downloaded_file_name) { win_friendly_path(::File.join(package_save_dir, 'VeeamBackup&Replication_9.5.0.711.iso')) } + let(:package_save_dir) { win_clean_path(::File.join(Chef::Config[:file_cache_path], 'package')) } + let(:downloaded_file_name) { win_clean_path(::File.join(package_save_dir, 'VeeamBackup&Replication_9.5.0.711.iso')) } it 'converges successfully' do expect(chef_run).to install_veeam_prerequisites('Install Veeam Prerequisites') @@ -44,11 +44,11 @@ expect(chef_run).to run_powershell_script('Load Veeam media') expect(chef_run).to run_ruby_block('Install the .NET 4.5.2') expect(chef_run).to run_ruby_block('Install the SQL Management Tools') - expect(chef_run).to create_template(win_friendly_path(::File.join(Chef::Config[:file_cache_path], 'ConfigurationFile.ini'))) + expect(chef_run).to create_template(win_clean_path(::File.join(Chef::Config[:file_cache_path], 'ConfigurationFile.ini'))) expect(chef_run).to run_ruby_block('Install the SQL Express') expect(chef_run).to run_ruby_block('Check SQL Install State') - expect(chef_run).to delete_file(win_friendly_path(::File.join(Chef::Config[:file_cache_path], 'ConfigurationFile.ini'))) - expect(chef_run).to delete_file(win_friendly_path(::File.join(Chef::Config[:file_cache_path], 'sql_build_script.ps1'))) + expect(chef_run).to delete_file(win_clean_path(::File.join(Chef::Config[:file_cache_path], 'ConfigurationFile.ini'))) + expect(chef_run).to delete_file(win_clean_path(::File.join(Chef::Config[:file_cache_path], 'sql_build_script.ps1'))) expect(chef_run).to delete_windows_task('Remove SQL Install Task') reboot_handler = chef_run.reboot('DotNet Install Complete') diff --git a/spec/unit/lwrps/veeam_proxy_add_spec.rb b/spec/unit/lwrps/veeam_proxy_add_spec.rb index 20e54ef..1ae6208 100644 --- a/spec/unit/lwrps/veeam_proxy_add_spec.rb +++ b/spec/unit/lwrps/veeam_proxy_add_spec.rb @@ -61,8 +61,8 @@ end let(:node) { runner.node } let(:chef_run) { runner.converge(described_recipe) } - let(:package_save_dir) { win_friendly_path(::File.join(Chef::Config[:file_cache_path], 'package')) } - let(:downloaded_file_name) { win_friendly_path(::File.join(package_save_dir, 'VeeamBackup_Replication_9.5.0.711.iso')) } + let(:package_save_dir) { win_clean_path(::File.join(Chef::Config[:file_cache_path], 'package')) } + let(:downloaded_file_name) { win_clean_path(::File.join(package_save_dir, 'VeeamBackup_Replication_9.5.0.711.iso')) } it 'converges successfully' do expect { chef_run }.not_to raise_error diff --git a/spec/unit/lwrps/veeam_proxy_remove_spec.rb b/spec/unit/lwrps/veeam_proxy_remove_spec.rb index 160bfc7..5a2f44b 100644 --- a/spec/unit/lwrps/veeam_proxy_remove_spec.rb +++ b/spec/unit/lwrps/veeam_proxy_remove_spec.rb @@ -57,8 +57,8 @@ end let(:node) { runner.node } let(:chef_run) { runner.converge(described_recipe) } - let(:package_save_dir) { win_friendly_path(::File.join(Chef::Config[:file_cache_path], 'package')) } - let(:downloaded_file_name) { win_friendly_path(::File.join(package_save_dir, 'VeeamBackup_Replication_9.5.0.711.iso')) } + let(:package_save_dir) { win_clean_path(::File.join(Chef::Config[:file_cache_path], 'package')) } + let(:downloaded_file_name) { win_clean_path(::File.join(package_save_dir, 'VeeamBackup_Replication_9.5.0.711.iso')) } it 'converges successfully' do allow(Mixlib::ShellOut).to receive(:new).with(/Check if Host is registered/, environment_var).and_return(true_shell) diff --git a/spec/unit/lwrps/veeam_server_spec.rb b/spec/unit/lwrps/veeam_server_spec.rb index f463921..7ef6643 100644 --- a/spec/unit/lwrps/veeam_server_spec.rb +++ b/spec/unit/lwrps/veeam_server_spec.rb @@ -36,8 +36,8 @@ end let(:node) { runner.node } let(:chef_run) { runner.converge(described_recipe) } - let(:package_save_dir) { win_friendly_path(::File.join(Chef::Config[:file_cache_path], 'package')) } - let(:downloaded_file_name) { win_friendly_path(::File.join(package_save_dir, 'VeeamBackup&Replication_9.5.0.711.iso')) } + let(:package_save_dir) { win_clean_path(::File.join(Chef::Config[:file_cache_path], 'package')) } + let(:downloaded_file_name) { win_clean_path(::File.join(package_save_dir, 'VeeamBackup&Replication_9.5.0.711.iso')) } it 'converges successfully' do expect(chef_run).to install_veeam_prerequisites('Install Veeam Prerequisites') diff --git a/spec/unit/lwrps/veeam_upgrade_spec.rb b/spec/unit/lwrps/veeam_upgrade_spec.rb index 606668f..64a191b 100644 --- a/spec/unit/lwrps/veeam_upgrade_spec.rb +++ b/spec/unit/lwrps/veeam_upgrade_spec.rb @@ -15,7 +15,7 @@ context 'Install Veeam Backup and Recovery Console' do platforms = { 'windows' => { - 'versions' => %w(2012) # 2012R2 2016) + 'versions' => %w(2012 2012R2 2016) } } platforms.each do |platform, components| @@ -38,8 +38,8 @@ end let(:node) { runner.node } let(:chef_run) { runner.converge(described_recipe) } - let(:package_save_dir) { win_friendly_path(::File.join(Chef::Config[:file_cache_path], 'package')) } - let(:downloaded_file_name) { win_friendly_path(::File.join(package_save_dir, 'VeeamBackup_Replication_9.5.0.1536.Update3.iso')) } + let(:package_save_dir) { win_clean_path(::File.join(Chef::Config[:file_cache_path], 'package')) } + let(:downloaded_file_name) { win_clean_path(::File.join(package_save_dir, 'VeeamBackup_Replication_9.5.0.1536.Update3.iso')) } it 'converges successfully' do expect { chef_run }.not_to raise_error @@ -68,8 +68,8 @@ end it 'should extract the media from a zip' do node.normal['veeam']['installer']['update_url'] = 'http://download/VeeamBackup&Replication_9.5.0.1536.Update3.zip' - downloaded_file_name = win_friendly_path(::File.join(package_save_dir, 'VeeamBackup_Replication_9.5.0.1536.Update3.zip')) - installer_path = win_friendly_path(::File.join(::Chef::Config[:file_cache_path], 'Veeam/VeeamBackup_Replication_9.5.0.1536.Update3/Updates')) + downloaded_file_name = win_clean_path(::File.join(package_save_dir, 'VeeamBackup_Replication_9.5.0.1536.Update3.zip')) + installer_path = win_clean_path(::File.join(::Chef::Config[:file_cache_path], 'Veeam/VeeamBackup_Replication_9.5.0.1536.Update3/Updates')) expect(chef_run).to create_remote_file(downloaded_file_name) expect(chef_run).to unzip_windows_zipfile(installer_path) expect(chef_run).to delete_file(downloaded_file_name) diff --git a/spec/windows_helper.rb b/spec/windows_helper.rb index 22771ad..090abde 100644 --- a/spec/windows_helper.rb +++ b/spec/windows_helper.rb @@ -25,6 +25,7 @@ # limitations under the License. # Windows Helper Method # +require 'chef/util/path_helper' def mock_windows_system_framework allow_any_instance_of(Chef::Recipe) .to receive(:wmi_property_from_query) @@ -45,6 +46,10 @@ def mock_windows_system_framework .and_return(false) end +def win_clean_path(path) + Chef::Util::PathHelper.cleanpath(path) +end + def win_friendly_path(path) path.gsub(::File::SEPARATOR, ::File::ALT_SEPARATOR || '\\') if path end diff --git a/templates/sql_server/sql_build_script.ps1.erb b/templates/sql_server/sql_build_script.ps1.erb index d2fc482..f743e6f 100644 --- a/templates/sql_server/sql_build_script.ps1.erb +++ b/templates/sql_server/sql_build_script.ps1.erb @@ -1,6 +1,13 @@ # Install SQL Server -<%= @sql_build_command %> | Out-File <%= @outputFilePath %> +if (Test-Path -Path <%= @sql_install_media %>\SQLEXPR_x64_ENU.exe){ + $installer_path = "<%= @sql_install_media %>\SQLEXPR_x64_ENU.exe" +} else { + $installer_path = "<%= @sql_install_media %>\SqlExpress\2016SP1\SQLEXPR_x64_ENU.exe" +} + +& $installer_path <%= @sql_build_command %> | Out-File <%= @outputFilePath %> + $results = @{} $results.Add('output','Successfully installed SQL Server') diff --git a/test/inspec/9.5.4.2399/catalog/README.md b/test/inspec/9.5.4.2399/catalog/README.md new file mode 100644 index 0000000..8e52bbc --- /dev/null +++ b/test/inspec/9.5.4.2399/catalog/README.md @@ -0,0 +1,3 @@ +# Example InSpec Profile + +This example shows the implementation of an InSpec [profile](../../docs/profiles.rst). diff --git a/test/inspec/9.5.4.2399/catalog/controls/catalog.rb b/test/inspec/9.5.4.2399/catalog/controls/catalog.rb new file mode 100644 index 0000000..7d807fa --- /dev/null +++ b/test/inspec/9.5.4.2399/catalog/controls/catalog.rb @@ -0,0 +1,19 @@ +control 'catalog-feature-installed' do + impact 1.0 + title 'Verify Veeam Backup Catalog installed' + desc 'Check if the Veeam Backup Catalog instance is installed and configured' + + describe port(9393) do + it { should be_listening } + end + + describe service('VeeamCatalogSvc') do + it { should be_running } + its('startmode') { should match('Auto') } + end + + describe package('Veeam Backup Catalog') do + it { should be_installed } + its('version') { should eq '9.5.4.2399' } + end +end diff --git a/test/inspec/9.5.4.2399/catalog/inspec.yml b/test/inspec/9.5.4.2399/catalog/inspec.yml new file mode 100644 index 0000000..318a001 --- /dev/null +++ b/test/inspec/9.5.4.2399/catalog/inspec.yml @@ -0,0 +1,8 @@ +name: backup_catalog +title: Veeam Backup Catalog Server +maintainer: 'Exosphere Data, LLC' +copyright: 'Exosphere Data, LLC' +copyright_email: chef@exospheredata.com +license: All Rights Reserved +summary: An InSpec Compliance Profile for Veeam Backup Catalog Server +version: 0.1.0 diff --git a/test/inspec/9.5.4.2399/catalog/libraries/.gitkeep b/test/inspec/9.5.4.2399/catalog/libraries/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/inspec/9.5.4.2399/console/README.md b/test/inspec/9.5.4.2399/console/README.md new file mode 100644 index 0000000..8e52bbc --- /dev/null +++ b/test/inspec/9.5.4.2399/console/README.md @@ -0,0 +1,3 @@ +# Example InSpec Profile + +This example shows the implementation of an InSpec [profile](../../docs/profiles.rst). diff --git a/test/inspec/9.5.4.2399/console/controls/console.rb b/test/inspec/9.5.4.2399/console/controls/console.rb new file mode 100644 index 0000000..ba8a109 --- /dev/null +++ b/test/inspec/9.5.4.2399/console/controls/console.rb @@ -0,0 +1,14 @@ +control 'console-feature-installed' do + impact 1.0 + title 'Verify Veeam Backup and Recovery Console installed' + desc 'Check if the Veeam Backup and Recovery Console instance is installed and configured' + + describe port(6170) do + it { should be_listening } + end + + describe package('Veeam Backup & Replication Console') do + it { should be_installed } + its('version') { should eq '9.5.4.2399' } + end +end diff --git a/test/inspec/9.5.4.2399/console/inspec.yml b/test/inspec/9.5.4.2399/console/inspec.yml new file mode 100644 index 0000000..4df1405 --- /dev/null +++ b/test/inspec/9.5.4.2399/console/inspec.yml @@ -0,0 +1,8 @@ +name: veeam_vbr_console +title: Veeam Backup and Recovery Console +maintainer: 'Exosphere Data, LLC' +copyright: 'Exosphere Data, LLC' +copyright_email: chef@exospheredata.com +license: All Rights Reserved +summary: An InSpec Compliance Profile for Veeam Backup and Recovery Console +version: 0.1.0 diff --git a/test/inspec/9.5.4.2399/console/libraries/.gitkeep b/test/inspec/9.5.4.2399/console/libraries/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/inspec/9.5.4.2399/prerequisites/README.md b/test/inspec/9.5.4.2399/prerequisites/README.md new file mode 100644 index 0000000..8e52bbc --- /dev/null +++ b/test/inspec/9.5.4.2399/prerequisites/README.md @@ -0,0 +1,3 @@ +# Example InSpec Profile + +This example shows the implementation of an InSpec [profile](../../docs/profiles.rst). diff --git a/test/inspec/9.5.4.2399/prerequisites/controls/prerequisites.rb b/test/inspec/9.5.4.2399/prerequisites/controls/prerequisites.rb new file mode 100644 index 0000000..37ed1f1 --- /dev/null +++ b/test/inspec/9.5.4.2399/prerequisites/controls/prerequisites.rb @@ -0,0 +1,20 @@ +control 'prerequisites-feature-installed' do + impact 1.0 + title 'Verify Veeam Prerequisites installed' + desc 'Check if the Veeam Prerequisites are installed and configured' + + describe package('Microsoft System CLR Types for SQL Server 2014') do + it { should be_installed } + its('version') { should eq '12.0.2402.11' } + end + + describe package('Microsoft SQL Server 2014 Management Objects (x64)') do + it { should be_installed } + its('version') { should eq '12.0.2000.8' } + end + + describe package('SQL Server 2016 Database Engine Services') do + it { should be_installed } + its('version') { should eq '13.1.4001.0' } + end +end diff --git a/test/inspec/9.5.4.2399/prerequisites/inspec.yml b/test/inspec/9.5.4.2399/prerequisites/inspec.yml new file mode 100644 index 0000000..fdc61b4 --- /dev/null +++ b/test/inspec/9.5.4.2399/prerequisites/inspec.yml @@ -0,0 +1,8 @@ +name: veeam_prerequisites +title: Veeam Prerequisites +maintainer: 'Exosphere Data, LLC' +copyright: 'Exosphere Data, LLC' +copyright_email: chef@exospheredata.com +license: All Rights Reserved +summary: An InSpec Compliance Profile for Veeam Prerequisites +version: 0.1.0 diff --git a/test/inspec/9.5.4.2399/prerequisites/libraries/.gitkeep b/test/inspec/9.5.4.2399/prerequisites/libraries/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/inspec/9.5.4.2399/prerequisites_nosql/README.md b/test/inspec/9.5.4.2399/prerequisites_nosql/README.md new file mode 100644 index 0000000..8e52bbc --- /dev/null +++ b/test/inspec/9.5.4.2399/prerequisites_nosql/README.md @@ -0,0 +1,3 @@ +# Example InSpec Profile + +This example shows the implementation of an InSpec [profile](../../docs/profiles.rst). diff --git a/test/inspec/9.5.4.2399/prerequisites_nosql/controls/prerequisites.rb b/test/inspec/9.5.4.2399/prerequisites_nosql/controls/prerequisites.rb new file mode 100644 index 0000000..1946d91 --- /dev/null +++ b/test/inspec/9.5.4.2399/prerequisites_nosql/controls/prerequisites.rb @@ -0,0 +1,15 @@ +control 'prerequisites-feature-installed' do + impact 1.0 + title 'Verify Veeam Prerequisites installed' + desc 'Check if the Veeam Prerequisites are installed and configured' + + describe package('Microsoft System CLR Types for SQL Server 2014') do + it { should be_installed } + its('version') { should eq '12.0.2402.11' } + end + + describe package('Microsoft SQL Server 2014 Management Objects (x64)') do + it { should be_installed } + its('version') { should eq '12.0.2000.8' } + end +end diff --git a/test/inspec/9.5.4.2399/prerequisites_nosql/inspec.yml b/test/inspec/9.5.4.2399/prerequisites_nosql/inspec.yml new file mode 100644 index 0000000..fdc61b4 --- /dev/null +++ b/test/inspec/9.5.4.2399/prerequisites_nosql/inspec.yml @@ -0,0 +1,8 @@ +name: veeam_prerequisites +title: Veeam Prerequisites +maintainer: 'Exosphere Data, LLC' +copyright: 'Exosphere Data, LLC' +copyright_email: chef@exospheredata.com +license: All Rights Reserved +summary: An InSpec Compliance Profile for Veeam Prerequisites +version: 0.1.0 diff --git a/test/inspec/9.5.4.2399/prerequisites_nosql/libraries/.gitkeep b/test/inspec/9.5.4.2399/prerequisites_nosql/libraries/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/inspec/9.5.4.2399/server/README.md b/test/inspec/9.5.4.2399/server/README.md new file mode 100644 index 0000000..8e52bbc --- /dev/null +++ b/test/inspec/9.5.4.2399/server/README.md @@ -0,0 +1,3 @@ +# Example InSpec Profile + +This example shows the implementation of an InSpec [profile](../../docs/profiles.rst). diff --git a/test/inspec/9.5.4.2399/server/controls/server.rb b/test/inspec/9.5.4.2399/server/controls/server.rb new file mode 100644 index 0000000..f362025 --- /dev/null +++ b/test/inspec/9.5.4.2399/server/controls/server.rb @@ -0,0 +1,19 @@ +control 'Server-feature-installed' do + impact 1.0 + title 'Verify Veeam Backup Server installed' + desc 'Check if the Veeam Backup Server instance is installed and configured' + + describe port(9392) do + it { should be_listening } + end + + describe service('VeeamBackupSvc') do + it { should be_running } + its('startmode') { should match('Auto') } + end + + describe package('Veeam Backup & Replication Server') do + it { should be_installed } + its('version') { should eq '9.5.4.2399' } + end +end diff --git a/test/inspec/9.5.4.2399/server/inspec.yml b/test/inspec/9.5.4.2399/server/inspec.yml new file mode 100644 index 0000000..a64fab7 --- /dev/null +++ b/test/inspec/9.5.4.2399/server/inspec.yml @@ -0,0 +1,8 @@ +name: backup_server +title: Veeam Backup and Recovery Server +maintainer: 'Exosphere Data, LLC' +copyright: 'Exosphere Data, LLC' +copyright_email: chef@exospheredata.com +license: All Rights Reserved +summary: An InSpec Compliance Profile for Veeam Backup and Recovery Server +version: 0.1.0 diff --git a/test/inspec/9.5.4.2399/server/libraries/.gitkeep b/test/inspec/9.5.4.2399/server/libraries/.gitkeep new file mode 100644 index 0000000..e69de29