Skip to content

Commit

Permalink
optionally move VM to under given OU in AD once created. folder sync …
Browse files Browse the repository at this point in the history
…optimizations
  • Loading branch information
jagorjat committed Jan 6, 2015
1 parent ca47dd3 commit 7603209
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 113 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,35 @@ If your local machine do not have direct access to the machine that hosts VMM, b
conf.proxy_server_address = 'my-proxy-to-vmm'
```

### Active Directory settings ( optional )

You can tell the provider to move your VM under some particular OU once it's created.
Here are required options you need to specify for that.

#### ad_server

URL of AD server. Can be derived by running **echo %LOGONSERVER%** command in CMD of the VM environment.
Example:
```
conf.ad_server = 'my-ad-server.some.domain.local'
```

#### ad_source_path

Base DN container where VM appears(and it will be moved from) once it's created.
Example:
```
conf.ad_source_path = 'CN=Computers,DC=some,DC=domain,DC=local'
```

#### ad_target_path

New AD path where VM should be moved to.
Example:
```
conf.ad_target_path = 'OU=Vagrant,OU=Chef-Nodes,DC=some,DC=domain,DC=local'
```

## Troubleshooting

### Hangs on waiting machine to boot
Expand Down
8 changes: 7 additions & 1 deletion lib/vagrant-vmm/action/import.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@ def call(env)
proxy_server_address: env[:machine].provider_config.proxy_server_address,
vm_name: env[:machine].config.vm.hostname,
vm_template_name: env[:machine].provider_config.vm_template_name,
vm_host_group_name: env[:machine].provider_config.vm_host_group_name
vm_host_group_name: env[:machine].provider_config.vm_host_group_name,
ad_server: env[:machine].provider_config.ad_server,
ad_source_path: env[:machine].provider_config.ad_source_path,
ad_target_path: env[:machine].provider_config.ad_target_path
}

#
env[:ui].detail("Creating and registering VM in the VMM (#{vmm_server_address})...")
if options[:ad_server] && options[:ad_source_path] && options[:ad_target_path]
env[:ui].detail(" ..and moving it under #{options[:ad_target_path]} after it's created.")
end
server = env[:machine].provider.driver.import(options)
env[:ui].detail("Successfully created the VM with name: #{server['name']}")
env[:machine].id = server["id"]
Expand Down
15 changes: 13 additions & 2 deletions lib/vagrant-vmm/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,25 @@ class Config < Vagrant.plugin("2", :config)
attr_accessor :vm_host_group_name
# @return [String]
attr_accessor :vm_address
# @return [String]
attr_accessor :ad_server
# @return [String]
attr_accessor :ad_source_path
# @return [String]
attr_accessor :ad_target_path



def initialize
@ip_address_timeout = UNSET_VALUE
@proxy_server_address = UNSET_VALUE
@proxy_server_address = nil
@vmm_server_address = UNSET_VALUE
@vm_template_name = UNSET_VALUE
@vm_host_group_name = UNSET_VALUE
@vm_address = UNSET_VALUE
@vm_address = nil
@ad_server = nil
@ad_source_path = nil
@ad_target_path = nil
end

def finalize!
Expand Down
6 changes: 4 additions & 2 deletions lib/vagrant-vmm/driver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,10 @@ def execute_powershell(path, options, &block)
options = options || {}
ps_options = []
options.each do |key, value|
ps_options << "-#{key}"
ps_options << "'#{value}'"
unless value.nil?
ps_options << "-#{key}"
ps_options << "'#{value}'"
end
end

# Always have a stop error action for failures
Expand Down
37 changes: 32 additions & 5 deletions lib/vagrant-vmm/scripts/import_vm.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ Param(
[string]$vm_template_name,
[Parameter(Mandatory=$true)]
[string]$vm_host_group_name,
[string]$proxy_server_address=$null
[string]$proxy_server_address=$null,
[string]$ad_server=$null,
[string]$ad_source_path=$null,
[string]$ad_target_path=$null
)

# Include the following modules
Expand All @@ -20,9 +23,11 @@ $script_block = {
# external vars
$vm_name = $using:vm_name
$vm_host_group_name = $using:vm_host_group_name
$vmm_credential = $using:vmm_credential
$server_address = $using:vmm_server_address
$vm_template_name = $using:vm_template_name
$ad_server = $using:ad_server
$ad_source_path = $using:ad_source_path
$ad_target_path = $using:ad_target_path

$description = "VM created by vagrant for testing purposes"
$MinFreeSpaceGB = 300 #
Expand Down Expand Up @@ -52,7 +57,6 @@ $script_block = {
DiskSpaceGB=$MinFreeSpaceGB;
VMName=$vm_name;
VMHostGroup=$VMHostGroup;
VMMServer=$vmmServer
}

$VMHost = $null
Expand Down Expand Up @@ -86,14 +90,37 @@ $script_block = {
DelayStartSeconds = $(Get-Random -Minimum 20 -Maximum 100)
}

New-SCVirtualMachine @vmCreateParams
$vm = New-SCVirtualMachine @vmCreateParams
} else {
Write-Error "Cannot find suitable host for the VM."
}
} else {
Write-Warning "Machine $vm_name already exists on host $($vm.VMHost.Name)"
$vm
}
# try to move it in AD
try
{
# move it to under AD path if required
if ($ad_target_path -ne $null -and $ad_source_path -ne $null -and $ad_server -ne $null)
{
$cred_param = @{}
if ($proxy_credential)
{
# if proxy used to overcome credssp auth
$cred_param["Credential"] = $proxy_credential
}
$ad_res = Get-ADComputer -Identity:"CN=$vm_name,$ad_source_path" -Server:$ad_server -ErrorAction Ignore @cred_param
if ( $ad_res -ne $null )
{
Move-ADObject -Identity:"CN=$vm_name,$ad_source_path" -TargetPath:$ad_target_path -Server:$ad_server @cred_param
}
}
} catch
{
Write-Warning "Couldn't move under specified OU: $_"
}
# return vm object
$vm
}

$vm = execute $script_block $vmm_server_address $proxy_server_address
Expand Down
169 changes: 86 additions & 83 deletions lib/vagrant-vmm/scripts/sync_folders.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Param(
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
. ([System.IO.Path]::Combine($Dir, "utils\manage_credentials.ps1"))
. ([System.IO.Path]::Combine($Dir, "utils\manage_trusted_hosts.ps1"))

# Sync flow:
# get list of files to sync, compare hashes with the remote ones
Expand All @@ -32,13 +33,7 @@ $delimiter = " || "
$creds_to_vm = Get-Creds $vm_address "Credentials for access to the VM ($vm_address) via WinRM" $winrm_vm_username $winrm_vm_password

# add to trusted hosts
$trusted_hosts = get-item wsman:\localhost\Client\TrustedHosts
if ( !$trusted_hosts.Value.Contains($vm_address) )
{
Write-host "Adding $vm_address to trusted host list"
$new_th_values = "$($trusted_hosts.Value),$vm_address"
set-item wsman:\localhost\Client\TrustedHosts $new_th_values -Force
}
Add-To-Trusted $vm_address


function Get-file-hash($source_paths, $delimiter) {
Expand Down Expand Up @@ -107,6 +102,7 @@ if (!$destination_files) {
$destination_files = @{}
}

$sync_required = $false
# compare hashes and derive what should be copied over and what removed
foreach ( $hst_path in $folder_mappings.Keys )
{
Expand All @@ -117,102 +113,109 @@ foreach ( $hst_path in $folder_mappings.Keys )
}

Compare-Object -ReferenceObject $source_files[$hst_path] -DifferenceObject $destination_files[$guest_path] | ForEach-Object {
if ($_.SideIndicator -eq '=>') {
$remove_files[$guest_path] += $_.InputObject.Split($delimiter)[0]
} else {
$copy_files[$hst_path] += $_.InputObject.Split($delimiter)[0]
$obj_path = $_.InputObject.Split($delimiter)[0]
if ($obj_path -and $obj_path.Trim())
{
# if not empty
if ($_.SideIndicator -eq '=>') {
$remove_files[$guest_path] += $obj_path
} else {
$copy_files[$hst_path] += $obj_path
}
$sync_required = $true
}
}
}

# create file share on the remote machine
Invoke-Command -Session $(Get-session) -ScriptBlock {
$fileshare_dest = "$($env:SystemDrive)\vagrant-sync"
if (Test-path $fileshare_dest)
{
Remove-item "$fileshare_dest\*" -recurse -force
} else {
$sync_dir = New-item $fileshare_dest -itemtype directory
}
$shr = Get-SmbShare -Name "vagrant-sync" -ErrorAction Ignore
if ( $shr -eq $null )
{
Write-host "$(&hostname) :: Creating fileshare on the remote host in $fileshare_dest, granting access to $($env:USERDOMAIN)\$($env:USERNAME)"
$shr = New-SmbShare -Name "vagrant-sync" -Temporary -Path $fileshare_dest -FullAccess "$($env:USERDOMAIN)\$($env:USERNAME)"
}
}

# get access to the fileshare from the current machine
Write-host "Getting access from the current machine to the created fileshare (\\$vm_address\vagrant-sync)"
$vagrant_sync_drive = New-PSDrive -Name 'V' -PSProvider 'FileSystem' -Root "\\$vm_address\vagrant-sync" -Credential $creds_to_vm

Write-host "Syncing files to fileshare..."
foreach ( $hst_path in $copy_files.Keys)
if ( $sync_required )
{
$current = 0
$total = $copy_files[$hst_path].Count
# copy files to the fileshare
foreach( $file in $copy_files[$hst_path] )
{
$current += 1
$file_path = $hst_path + $file
$guest_path = $folder_mappings[$hst_path]
$guest_path = [System.IO.Path]::GetFullPath("$($vagrant_sync_drive.root)\$guest_path")
Write-progress -Activity "Syncing $hst_path with $guest_path" -PercentComplete $($current*100/$total) -Status "Copying $file"
if (Test-Path $file_path -pathtype container)
# create file share on the remote machine
Invoke-Command -Session $(Get-session) -ScriptBlock {
$fileshare_dest = "$($env:SystemDrive)\vagrant-sync"
if (Test-path $fileshare_dest)
{
# folder
$out = New-Item $file_path -itemtype directory -ErrorAction Ignore
Remove-item "$fileshare_dest\*" -recurse -force
} else {
# file
$file_dir = split-path $file
$out = New-item "$guest_path\$file_dir" -itemtype directory -ErrorAction Ignore
Copy-Item $file_path "$guest_path\$file" -recurse
$sync_dir = New-item $fileshare_dest -itemtype directory
}
$shr = Get-SmbShare -Name "vagrant-sync" -ErrorAction Ignore
if ( $shr -eq $null )
{
Write-host "$(&hostname) :: Creating fileshare on the remote host in $fileshare_dest, granting access to $($env:USERDOMAIN)\$($env:USERNAME)"
$shr = New-SmbShare -Name "vagrant-sync" -Temporary -Path $fileshare_dest -FullAccess "$($env:USERDOMAIN)\$($env:USERNAME)"
}
}
}

# copy from fileshare to the dest locations on the remote machine
# as well as remove files that shouldn't be there
Invoke-Command -Session $(Get-session) -ScriptBlock {
$remove_files = $using:remove_files
$fileshare_dest = "$($env:SystemDrive)\vagrant-sync"
write-host "$(&hostname) :: Distributing files from $fileshare_dest..."
# remove files
$total = $remove_files.Keys.Count
$current = 0
foreach ( $g_path in $remove_files.Keys )
# get access to the fileshare from the current machine
Write-host "Getting access from the current machine to the created fileshare (\\$vm_address\vagrant-sync)"
$vagrant_sync_drive = New-PSDrive -Name 'V' -PSProvider 'FileSystem' -Root "\\$vm_address\vagrant-sync" -Credential $creds_to_vm

Write-host "Syncing files to fileshare..."
foreach ( $hst_path in $copy_files.Keys)
{
$current += 1
Write-progress -Activity "Cleaning redundant files" -PercentComplete $($current*100/$total) -Status "Cleaning under: $g_path"
foreach ($r_file in $remove_files[$g_path])
$current = 0
$total = $copy_files[$hst_path].Count
# copy files to the fileshare
foreach( $file in $copy_files[$hst_path] )
{
Remove-Item $($g_path+$r_file) -recurse -force -ErrorAction Ignore
$current += 1
$file_path = $hst_path + $file
$guest_path = $folder_mappings[$hst_path]
$guest_path = [System.IO.Path]::GetFullPath("$($vagrant_sync_drive.root)\$guest_path")
Write-progress -Activity "Syncing $hst_path with $guest_path" -PercentComplete $($current*100/$total) -Status "Copying $file"
if (Test-Path $file_path -pathtype container)
{
# folder
$out = New-Item $file_path -itemtype directory -ErrorAction Ignore
} else {
# file
$file_dir = split-path $file
$out = New-item "$guest_path\$file_dir" -itemtype directory -ErrorAction Ignore
Copy-Item $file_path "$guest_path\$file" -recurse
}
}
}
$root_files_in_share = Get-ChildItem $fileshare_dest -Directory -ErrorAction Ignore
$total = $root_files_in_share.Count
$current = 0
#TODO: remove hard-code to SystemDrive
foreach ( $guest_path in $root_files_in_share )
{
$current += 1
Write-progress -Activity "Distributing files on the remote machine" -PercentComplete $($current*100/$total) -Status "Copying: $guest_path"
Copy-Item "$fileshare_dest\$guest_path" "$($env:SystemDrive)\" -recurse -force

# copy from fileshare to the dest locations on the remote machine
# as well as remove files that shouldn't be there
Invoke-Command -Session $(Get-session) -ScriptBlock {
$remove_files = $using:remove_files
$fileshare_dest = "$($env:SystemDrive)\vagrant-sync"
write-host "$(&hostname) :: Distributing files from $fileshare_dest..."
# remove files
$total = $remove_files.Keys.Count
$current = 0
foreach ( $g_path in $remove_files.Keys )
{
$current += 1
Write-progress -Activity "Cleaning redundant files" -PercentComplete $($current*100/$total) -Status "Cleaning under: $g_path"
foreach ($r_file in $remove_files[$g_path])
{
Remove-Item $($g_path+$r_file) -recurse -force -ErrorAction Ignore
}
}
$root_files_in_share = Get-ChildItem $fileshare_dest -Directory -ErrorAction Ignore
$total = $root_files_in_share.Count
$current = 0
#TODO: remove hard-code to SystemDrive
foreach ( $guest_path in $root_files_in_share )
{
$current += 1
Write-progress -Activity "Distributing files on the remote machine" -PercentComplete $($current*100/$total) -Status "Copying: $guest_path"
Copy-Item "$fileshare_dest\$guest_path" "$($env:SystemDrive)\" -recurse -force
}
}
} else # if there are something to copy or remove
{
Write-host "Skipping sync as there are nothing to sync."
}


# close session
Remove-PSSession -Id $session.Id

# remove vm_address from trusted hosts
$trusted_hosts = get-item wsman:\localhost\Client\TrustedHosts
if ( $trusted_hosts.Value.Contains($vm_address) )
{
Write-host "Removing $vm_address from trusted host list"
$new_th_values = $trusted_hosts.Value -replace ",?$vm_address", ""
set-item wsman:\localhost\Client\TrustedHosts $new_th_values -Force
}
Remove-From-Trusted $vm_address


$resultHash = $folder_mappings
$result = ConvertTo-Json $resultHash
Expand Down
Loading

0 comments on commit 7603209

Please sign in to comment.