Class: VagrantPlugins::WindowsDomain::Provisioner
- Inherits:
-
Object
- Object
- VagrantPlugins::WindowsDomain::Provisioner
- Defined in:
- lib/vagrant-windows-domain/provisioner.rb
Overview
Windows Domain Provisioner Plugin.
Connects and Removes a guest Machine from a Windows Domain.
Constant Summary collapse
- WINDOWS_DOMAIN_GUEST_RUNNER_PATH =
Default path for storing the transient script runner
"c:/tmp/vagrant-windows-domain-runner.ps1"
Instance Attribute Summary collapse
-
#old_computer_name ⇒ Object
The current Computer Name.
-
#restart_sleep_duration ⇒ Object
Returns the value of attribute restart_sleep_duration.
Instance Method Summary collapse
-
#configure(root_config) ⇒ Object
Configures the Provisioner.
-
#destroy ⇒ Object
Cleanup after a destroy action.
-
#generate_command_arguments(add_to_domain = true) ⇒ Object
Generates the argument list.
-
#generate_command_arguments_rename ⇒ Object
Generates the argument list for rename.
-
#generate_command_runner_script(add_to_domain = true) ⇒ String
Generates a PowerShell runner script from an ERB template.
-
#get_guest_computer_name(machine) ⇒ Object
Gets the Computer Name from the guest machine.
-
#initialize(machine, config) ⇒ Provisioner
constructor
Constructs the Provisioner Plugin.
- #is_joined_to_domain ⇒ Object
- #is_part_of_domain(computer_name, domain) ⇒ Object
-
#join_domain ⇒ Object
Join the guest machine to a Windows Domain.
-
#leave_domain ⇒ Object
(also: #unjoin_domain)
Removes the guest machine from a Windows Domain.
-
#provision ⇒ Object
Run the Provisioner!.
-
#remove_command_runner_script ⇒ Object
Remove temporary run script as it may contain sensitive plain-text credentials.
-
#restart_guest ⇒ Object
Restarts the Computer and waits.
-
#run_remote_command_runner(script_path) ⇒ boolean
Runs the PowerShell script on the guest machine.
-
#set_credentials ⇒ Object
Ensure credentials are provided.
-
#verify_binary(binary) ⇒ Object
Verify a binarycommand is executable on the guest machine.
-
#verify_guest_capability ⇒ Object
Verify that we can call the remote operations.
-
#windows? ⇒ Boolean
Is the guest Windows?.
-
#write_command_runner_script(script) ⇒ String
Writes the PowerShell runner script to a location on the guest.
Constructor Details
#initialize(machine, config) ⇒ Provisioner
Constructs the Provisioner Plugin.
36 37 38 39 40 41 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 36 def initialize(machine, config) super @logger = Log4r::Logger.new("vagrant::provisioners::vagrant_windows_domain") @restart_sleep_duration = 10 end |
Instance Attribute Details
#old_computer_name ⇒ Object
The current Computer Name.
Used to determine whether or not we need to rename the computer on join. This parameter should not be manually set.
29 30 31 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 29 def old_computer_name @old_computer_name end |
#restart_sleep_duration ⇒ Object
Returns the value of attribute restart_sleep_duration.
23 24 25 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 23 def restart_sleep_duration @restart_sleep_duration end |
Instance Method Details
#configure(root_config) ⇒ Object
Configures the Provisioner.
46 47 48 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 46 def configure(root_config) raise WindowsDomainError, :unsupported_platform if !windows? end |
#destroy ⇒ Object
Cleanup after a destroy action.
This is the method called when destroying a machine that allows for any state related to the machine created by the provisioner to be cleaned up.
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 153 def destroy if @config && @config.domain != nil if is_joined_to_domain() set_credentials result = leave_domain if result @logger.debug("Need to reboot to leave the domain correctly") restart_guest end end else @logger.debug("Not leaving domain on `destroy` action - no valid configuration detected") return end end |
#generate_command_arguments(add_to_domain = true) ⇒ Object
Generates the argument list
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 238 def generate_command_arguments(add_to_domain=true) if add_to_domain params = {"-DomainName" => @config.domain } if @config.unsecure params["-Unsecure"] = nil else params["-Credential $credentials"] = nil end if @config.computer_name != nil && @config.computer_name != @old_computer_name params["-NewName"] = "'#{@config.computer_name}'" end if @config.ou_path params["-OUPath"] = "'#{@config.ou_path}'" end # Remove with unsecure join_params = @config..map { |a| "#{a}" }.join(',') if join_params.to_s != '' params["-Options"] = join_params end else params = {} if !@config.unsecure params["-UnjoinDomainCredential $credentials"] = nil end end params.map { |k,v| "#{k}" + (!v.nil? ? " #{v}": '') }.join(' ') end |
#generate_command_arguments_rename ⇒ Object
Generates the argument list for rename
228 229 230 231 232 233 234 235 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 228 def generate_command_arguments_rename params = {"-NewName" => @config.computer_name} params["-DomainCredential $credentials"] = nil join_params = @config..map { |a| "#{a}" }.join(',') params.map { |k,v| "#{k}" + (!v.nil? ? " #{v}": '') }.join(' ') + join_params end |
#generate_command_runner_script(add_to_domain = true) ⇒ String
Generates a PowerShell runner script from an ERB template
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 204 def generate_command_runner_script(add_to_domain=true) path = File.("../templates/runner.ps1", __FILE__) if @config.computer_name != nil && @old_computer_name != nil && @config.computer_name.casecmp(@old_computer_name) != 0 @config.rename = true end Vagrant::Util::TemplateRenderer.render(path, options: { config: @config, username: @config.username, password: @config.password, domain: @config.domain, computer_name: @config.computer_name, ou_path: @config.ou_path, add_to_domain: add_to_domain, unsecure: @config.unsecure, rename: @config.rename, parameters: generate_command_arguments(add_to_domain) }, options_rename: { parameters: generate_command_arguments_rename }) end |
#get_guest_computer_name(machine) ⇒ Object
Gets the Computer Name from the guest machine
333 334 335 336 337 338 339 340 341 342 343 344 345 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 333 def get_guest_computer_name(machine) computerName = "" machine.communicate.shell.powershell("$env:COMPUTERNAME") do |type, data| if !data.chomp.empty? if [:stderr, :stdout].include?(type) computerName = data.chomp @logger.info("Detected guest computer name: #{computerName}") end end end computerName end |
#is_joined_to_domain ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 68 def is_joined_to_domain() command = " function Test-JoinedToADomain(){\n $computerSystem = gwmi win32_computersystem\n $partOfDomain = $computerSystem.PartOfDomain\n if ($partofDomain) {\n exit 0\n } else {\n exit 1\n }\n }\n Test-JoinedToADomain\n EOH\n @machine.communicate.test(command, sudo: true)\nend\n" |
#is_part_of_domain(computer_name, domain) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 51 def is_part_of_domain(computer_name, domain) command = " function Test-PartOfDomain($computerName, $domain){\n $computerSystem = gwmi win32_computersystem\n $partofDomain = ($computerSystem.Name -eq $computerName) -and ($computerSystem.PartOfDomain) -and ($computerSystem.Domain -eq $domain) \n\n if ($partofDomain) {\n exit 0\n } else {\n exit 1\n }\n }\n Test-PartOfDomain -computerName '\#{computer_name}' -domain '\#{domain}'\n EOH\n @machine.communicate.test(command, sudo: true)\nend\n" |
#join_domain ⇒ Object
Join the guest machine to a Windows Domain.
Generates, writes and runs a script to join a domain.
118 119 120 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 118 def join_domain run_remote_command_runner(write_command_runner_script(generate_command_runner_script(true))) end |
#leave_domain ⇒ Object Also known as: unjoin_domain
Removes the guest machine from a Windows Domain.
Generates, writes and runs a script to leave a domain.
125 126 127 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 125 def leave_domain run_remote_command_runner(write_command_runner_script(generate_command_runner_script(false))) end |
#provision ⇒ Object
Run the Provisioner!
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 86 def provision verify_guest_capability @old_computer_name = get_guest_computer_name(machine) result = is_part_of_domain(config.computer_name, config.domain) if result @machine.env.ui.say(:info, "Guest machine with computer name '#{config.computer_name}' is already a member of domain '#{config.domain}'") else @machine.env.ui.say(:info, "Connecting guest machine to domain '#{config.domain}' with computer name '#{config.computer_name}'") set_credentials result = join_domain remove_command_runner_script if result #Often requires 2 reboots to ensure that all AD stuff has been applied @logger.debug("Need to reboot to join the domain correctly - 1st reboot") restart_guest @logger.debug("Need to reboot to join the domain correctly - 2nd reboot") restart_guest end end end |
#remove_command_runner_script ⇒ Object
Remove temporary run script as it may contain sensitive plain-text credentials.
293 294 295 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 293 def remove_command_runner_script @machine.communicate.sudo("del #{WINDOWS_DOMAIN_GUEST_RUNNER_PATH}") end |
#restart_guest ⇒ Object
Restarts the Computer and waits
170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 170 def restart_guest @machine.env.ui.say(:info, "Restarting computer for updates to take effect.") = {} [:provision_ignore_sentinel] = false [:lock] = false @machine.action(:reload, ) Timeout.timeout(@machine.config.vm.boot_timeout) do begin sleep @restart_sleep_duration end until @machine.communicate.ready? end end |
#run_remote_command_runner(script_path) ⇒ boolean
Runs the PowerShell script on the guest machine.
Streams the output of the command to the UI
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 301 def run_remote_command_runner(script_path) @machine.ui.info(I18n.t( "vagrant_windows_domain.running")) opts = { elevated: true, error_check: true, error_key: nil, # use the error_class message key good_exit: 0, shell: :powershell } # A bit of an ugly dance, but this is how we get neat, colourised output and exit codes from a Powershell run last_type = nil new_line = "" error = false machine.communicate.sudo("powershell -ExecutionPolicy Bypass -OutputFormat Text -file #{script_path}", opts) do |type, data| if !data.chomp.empty? error = true if type == :stderr if [:stderr, :stdout].include?(type) color = type == :stdout ? :green : :red new_line = "\r\n" if last_type != nil and last_type != type last_type = type @machine.ui.info( new_line + data.chomp, color: color, new_line: false, prefix: false) end end end error == false end |
#set_credentials ⇒ Object
Ensure credentials are provided.
Get username/password from user if not provided as part of the config.
134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 134 def set_credentials if (config.username == nil) @logger.info("==> Requesting username as none provided") config.username = @machine.env.ui.ask("Please enter your domain username: ") else @logger.info("==> Using domain username: #{config.username}") end if (config.password == nil) @logger.info("==> Requesting password as none provided") config.password = @machine.env.ui.ask("Please enter your domain password (output will be hidden): ", {:echo => false}) end end |
#verify_binary(binary) ⇒ Object
Verify a binarycommand is executable on the guest machine.
191 192 193 194 195 196 197 198 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 191 def verify_binary(binary) @machine.communicate.sudo( "which #{binary}", error_class: WindowsDomainError, error_key: :binary_not_detected, domain: config.domain, binary: binary) end |
#verify_guest_capability ⇒ Object
Verify that we can call the remote operations. Required to add the computer to a Domain.
185 186 187 188 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 185 def verify_guest_capability verify_binary("Add-Computer") verify_binary("Remove-Computer") end |
#windows? ⇒ Boolean
Is the guest Windows?
348 349 350 351 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 348 def windows? # If using WinRM, we can assume we are on Windows @machine.config.vm.communicator == :winrm end |
#write_command_runner_script(script) ⇒ String
Writes the PowerShell runner script to a location on the guest.
276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/vagrant-windows-domain/provisioner.rb', line 276 def write_command_runner_script(script) guest_script_path = WINDOWS_DOMAIN_GUEST_RUNNER_PATH file = Tempfile.new(["vagrant-windows-domain-runner", "ps1"]) begin file.write(script) file.fsync file.close @machine.communicate.upload(file.path, guest_script_path) ensure file.close file.unlink end guest_script_path end |