diff --git a/lib/support/guest_customization.rb b/lib/support/guest_customization.rb index 3a1db90..c8cc46e 100644 --- a/lib/support/guest_customization.rb +++ b/lib/support/guest_customization.rb @@ -195,7 +195,7 @@ def guest_customization_identity_windows RbVmomi::VIM::CustomizationSysprep.new( guiUnattended: RbVmomi::VIM::CustomizationGuiUnattended.new( - timeZone: timezone.to_i || DEFAULT_WINDOWS_TIMEZONE, + timeZone: windows_timezone_convert(timezone || DEFAULT_WINDOWS_TIMEZONE), autoLogon: false, autoLogonCount: 1, password: customization_pass @@ -242,11 +242,36 @@ def valid_linux_timezone?(input) def valid_windows_timezone?(input) # Accept decimals and hex # See https://support.microsoft.com/en-us/help/973627/microsoft-time-zone-index-values - windows_timezone_pattern = /^([0-9]+|0x[0-9a-fA-F]+)$/ + windows_timezone_pattern = /^((-){,1}[0-9]+|0x[0-9a-fA-F]+)$/ input.to_s.match? windows_timezone_pattern end + # convert the value provided to a signed int + # + # @param input - Value to convert + # @returns [Integer] of converted value + def windows_timezone_convert(input) + mid = 2**(32 - 1) + max = 2**32 + if input.is_a?(String) + if input.match?(/^0x[0-9a-fA-F]+$/) + input = input.to_i(16) + else + input = input.to_i + end + end + if input.is_a?(Integer) + input = input + else + input = input.to_i(16) + end + if input >= mid + input -= max + end + input + end + # Check for format of Windows Product IDs # # @param [String] input String to check diff --git a/spec/unit/support/clone_vm_spec.rb b/spec/unit/support/clone_vm_spec.rb index d8a0776..a2222a0 100644 --- a/spec/unit/support/clone_vm_spec.rb +++ b/spec/unit/support/clone_vm_spec.rb @@ -271,5 +271,43 @@ expect(subject.networks_to_add.first[:name]).to eq "my-network-2" end end + + windows_timezone_tests = [ + ["Coordinated Universal Time", [0x80000050, "0x80000050", "-2147483568", -2147483568], -2147483568], + ["Eastern Time (US & Canada)", ["35", 35, 0x23, "0x23"], 35], + ["Central Time (US & Canada)", ["20", 20, 0x14, "0x14"], 20], + ["Dublin, Edinburgh, Lisbon, London", ["85", 85, "0x55", 0x55], 85], + ["Istanbul", [-2147483560, "-2147483560", 0x80000058, "0x80000058"], -2147483560], + ["Casablanca", [-2147483571, "-2147483571", 0x8000004d, "0x8000004d"], -2147483571], + ] + windows_timezone_tests.each do |this_timezone| + context "when windows guest_customization timezone for \"#{this_timezone[0]}\" is provided" do + this_timezone[1].each do |val| + before do + allow(event_manager).to receive(:QueryEvents).and_return([RbVmomi::VIM::CustomizationSucceeded()]) + options[:vm_os] = "windows" + options[:guest_customization] = { + timeout_task: 1, + timezone: val, + product_id: "D2N9P-3P6X9-2R39C-7RTCD-MDVJX", + org_name: "chef", + dns_domain: "chef.io", + dns_server_list: [], + dns_suffix_list: [], + } + end + it "helper method properly validates the passed timezone" do + expect(subject.valid_windows_timezone?(options[:guest_customization][:timezone])).to be_truthy + end + it "helper method properly converts the passed timezone to a 32-bit signed integer" do + expect(subject.windows_timezone_convert(options[:guest_customization][:timezone])).to eq this_timezone[2] + end + it "sets guest customization data with the correct timezone code" do + expect(source_vm).to receive(:CloneVM_Task).with(spec: a_hash_including(customization: a_hash_including(identity: a_hash_including(guiUnattended: a_hash_including(timeZone: this_timezone[2])))), folder: folder_id, name: vm_name).and_return(clone_vm_task) + subject.clone + end + end + end + end end end