Search code examples
powershellvagranthyper-v

How to use a powershell script during vagrant up on host correctly?


I am trying to execute a powershell script during vagrant up privileged and with elevated rights. I am using Vagrant 2.2.10 on an windows machine. The script lies in the same directory like the Vagrantfile. i have managed to get the correct trigger, but wasn't able to execute my powershell script correct with trigger.run.

Here is the relevant part of my Vagrantfile:

ENV['VAGRANT_EXPERIMENTAL'] = "typed_triggers"

Vagrant.configure("2") do |config|
override.trigger.before :'VagrantPlugins::HyperV::Action::StartInstance', type: :action do |trigger|
          trigger.ruby do |env, machine|
            machine.ui.info("------------------ Configure Node with Powershell Script -------------------")            
            trigger.run = {
              #privileged: "true"
              #powershell_elevated_interactive: "true"
              inline: <<-SHELL
              echo hhhhhhh > 123.log
              Write-Host "test"
              SHELL
           }            
           trigger.run = { path: './test.ps1'}
           trigger.run = { inline: "./test.ps1 -a 'test1' -b 'test2" }
           trigger.run = { privileged: "true",  powershell_elevated_interactive: "true", path: "powershell test.ps1", args: ["-a test1", "-b test2 "] }
           #trigger.run = { privileged: "true",  powershell_elevated_interactive: "true", :path => "test.ps1", :args => "testarg1, testarg2"} 
              
           machine.ui.info("------------------ Configuration of Node finished  -------------------") 
          end
        end 
    
      end 

In the vagrant.log i couldn't find any specific error that could help:

 INFO trigger: Firing trigger for action VagrantPlugins::HyperV::Action::StartInstance on guest server1
 INFO interface: info: Running action triggers before VagrantPlugins::HyperV::Action::StartInstance ...
 INFO interface: info: ==> server1: Running action triggers before VagrantPlugins::HyperV::Action::StartInstance ...
==> server1: Running action triggers before VagrantPlugins::HyperV::Action::StartInstance ...
DEBUG trigger: Running trigger 69600289-3cee-4dde-a9fa-2ac9bec33409...
 INFO interface: info: Running trigger...
 INFO interface: info: ==> server1: Running trigger...
==> server1: Running trigger...
 INFO interface: info: ------------------ Configure Node with Powershell Script -------------------
 INFO interface: info: ==> server1: ------------------ Configure Node with Powershell Script -------------------
==> server1: ------------------ Configure Node with Powershell Script -------------------
DEBUG provisioner: Provisioner defined: 
 INFO interface: info: ------------------ Configuration of Node finished  -------------------
 INFO interface: info: ==> server1: ------------------ Configuration of Node finished  -------------------
==> server1: ------------------ Configuration of Node finished  -------------------

None of the above trigger.runs worked. Hopefully anybody of you know how to fix this !!

How can i get this work ?

Thanks..


Solution

  • I found a solution. I use it to overcome the limitations of vagrant and add an additional network card to a different second public switch. You can use it to execute any powershell script:

    ENV['VAGRANT_EXPERIMENTAL'] = "typed_triggers"
    
    Vagrant.configure("2") do |config|  
        # Set ImageName
        config.vm.box = "REPO/YOURIMAGE"    
        config.vm.box_version  ="YOURVERSION"
     
        # Set network to Hyper-V Switch (define an external switch in hyperv and insert here)
        config.vm.network "public_network", bridge: "WAN - FIRST"
        
        # Add Additional network card and assign a different second public network
        # THIS DOES NOT WORK ON HYPER-V DUE LIMITATIONS OF VAGRANT 
        #config.vm.network "public_network", bridge: "WAN - SECOND"
    
        # WORKAROUND for all LIMITATIONS OF VAGRANT (execute a powershell script to handle hyper-v actions before startup of instance)
        # will be executed before the hyper-Instance will be started  
        secSwitch ='WAN - SECOND'
    
        config.vm.provider :hyperv do |vb, override|
    
        # Set vmname
        vb.vmname = "testmachine"
        # Execute a powershell script elevated and privileged (!!)
          override.trigger.before :'VagrantPlugins::HyperV::Action::StartInstance', type: :action do |trigger|
            trigger.run = { inline: "./hyperv-config-node.ps1 -VmName testmachine -SwitchName \"'#{secSwitch}'\" " }
          end
        end 
        # WORKAROUND (END)
    end
    

    and the powershell scripts hyperv-config-node.ps1 looks like this:

    param (
        [parameter (Mandatory=$true)]
        [string]$VmName,
        [parameter (Mandatory=$true)]
        [string]$SwitchName
    )
    
    try {
      Write-Host "------------------ Configure Node with Powershell Script : $VmName -------------------"
      Write-Host "VM-Machine: $VmName"
      Write-Host "Add Switch: $SwitchName"
      $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
      Write-Host "IsAdmin: " $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
      $vm = Hyper-V\Get-VM -Name $VmName -ErrorAction "stop" 
      Hyper-V\Add-VMNetworkAdapter $vm -Switch $SwitchName  
      Write-Host "------------------ Configuration of Node finished  -------------------"
    }
    catch {
      Write-Host "Failed to set VM's Second Nic: $_"
    }