mirror of
https://github.com/puppetlabs/vmpooler-provider-vsphere.git
synced 2026-01-26 03:18:41 -05:00
Merge pull request #29 from puppetlabs/vmpooler-dns-gcp
(RE-15124) Collect VMs IP for use with DNS Plugins
This commit is contained in:
commit
98b5fb1841
7 changed files with 100 additions and 4324 deletions
|
|
@ -3,7 +3,7 @@ PATH
|
||||||
specs:
|
specs:
|
||||||
vmpooler-provider-vsphere (2.1.0)
|
vmpooler-provider-vsphere (2.1.0)
|
||||||
rbvmomi2 (>= 3.1, < 4.0)
|
rbvmomi2 (>= 3.1, < 4.0)
|
||||||
vmpooler (~> 2.4)
|
vmpooler (~> 3.0)
|
||||||
|
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
|
|
@ -14,7 +14,7 @@ GEM
|
||||||
climate_control (1.2.0)
|
climate_control (1.2.0)
|
||||||
coderay (1.1.3)
|
coderay (1.1.3)
|
||||||
concurrent-ruby (1.2.2)
|
concurrent-ruby (1.2.2)
|
||||||
connection_pool (2.3.0)
|
connection_pool (2.4.0)
|
||||||
deep_merge (1.2.2)
|
deep_merge (1.2.2)
|
||||||
diff-lcs (1.5.0)
|
diff-lcs (1.5.0)
|
||||||
docile (1.4.0)
|
docile (1.4.0)
|
||||||
|
|
@ -146,7 +146,7 @@ GEM
|
||||||
thrift (0.18.1)
|
thrift (0.18.1)
|
||||||
tilt (2.1.0)
|
tilt (2.1.0)
|
||||||
unicode-display_width (2.4.2)
|
unicode-display_width (2.4.2)
|
||||||
vmpooler (2.4.0)
|
vmpooler (3.0.0)
|
||||||
concurrent-ruby (~> 1.1)
|
concurrent-ruby (~> 1.1)
|
||||||
connection_pool (~> 2.2)
|
connection_pool (~> 2.2)
|
||||||
deep_merge (~> 1.2)
|
deep_merge (~> 1.2)
|
||||||
|
|
@ -172,7 +172,6 @@ GEM
|
||||||
rspec (~> 3)
|
rspec (~> 3)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
universal-java-1.8
|
|
||||||
universal-java-11
|
universal-java-11
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
|
|
@ -188,4 +187,4 @@ DEPENDENCIES
|
||||||
yarjuf (>= 2.0)
|
yarjuf (>= 2.0)
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.2.29
|
2.4.10
|
||||||
|
|
|
||||||
7
install-gemfile-lock
Executable file
7
install-gemfile-lock
Executable file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# The container tag should closely match what is used in `docker/Dockerfile` in vmpooler-deployment
|
||||||
|
docker run -it --rm \
|
||||||
|
-v $(pwd):/app \
|
||||||
|
jruby:9.4.1.0-jdk11 \
|
||||||
|
/bin/bash -c 'apt-get update -qq && apt-get install -y --no-install-recommends make git netbase && cd /app && gem install bundler && bundle install --jobs 3; echo "LOCK_FILE_UPDATE_EXIT_CODE=$?"'
|
||||||
|
|
@ -51,6 +51,11 @@ module Vmpooler
|
||||||
'vsphere'
|
'vsphere'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def domain(pool_name)
|
||||||
|
dns_plugin_name = pool_config(pool_name)['dns_plugin']
|
||||||
|
dns_config(dns_plugin_name)
|
||||||
|
end
|
||||||
|
|
||||||
def folder_configured?(folder_title, base_folder, configured_folders, allowlist)
|
def folder_configured?(folder_title, base_folder, configured_folders, allowlist)
|
||||||
return true if allowlist&.include?(folder_title)
|
return true if allowlist&.include?(folder_title)
|
||||||
return false unless configured_folders.keys.include?(folder_title)
|
return false unless configured_folders.keys.include?(folder_title)
|
||||||
|
|
@ -387,6 +392,16 @@ module Vmpooler
|
||||||
vm_hash
|
vm_hash
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The inner method requires vmware tools running in the guest os
|
||||||
|
def get_vm_ip_address(vm_name, pool_name)
|
||||||
|
@connection_pool.with_metrics do |pool_object|
|
||||||
|
connection = ensured_vsphere_connection(pool_object)
|
||||||
|
vm_object = find_vm(pool_name, vm_name, connection)
|
||||||
|
vm_hash = generate_vm_hash(vm_object, pool_name)
|
||||||
|
return vm_hash['ip']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def create_config_spec(vm_name, template_name, extra_config)
|
def create_config_spec(vm_name, template_name, extra_config)
|
||||||
RbVmomi::VIM.VirtualMachineConfigSpec(
|
RbVmomi::VIM.VirtualMachineConfigSpec(
|
||||||
annotation: JSON.pretty_generate(
|
annotation: JSON.pretty_generate(
|
||||||
|
|
@ -540,9 +555,10 @@ module Vmpooler
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
def vm_ready?(_pool_name, vm_name)
|
def vm_ready?(pool_name, vm_name)
|
||||||
begin
|
begin
|
||||||
open_socket(vm_name, global_config[:config]['domain'])
|
domain = domain(pool_name)
|
||||||
|
open_socket(vm_name, domain)
|
||||||
rescue StandardError => _e
|
rescue StandardError => _e
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
@ -582,13 +598,28 @@ module Vmpooler
|
||||||
boottime = vm_object.runtime.bootTime if vm_object.runtime&.bootTime
|
boottime = vm_object.runtime.bootTime if vm_object.runtime&.bootTime
|
||||||
powerstate = vm_object.runtime.powerState if vm_object.runtime&.powerState
|
powerstate = vm_object.runtime.powerState if vm_object.runtime&.powerState
|
||||||
|
|
||||||
|
ip_maxloop = 60
|
||||||
|
ip_loop_delay = 1
|
||||||
|
ip_loop_count = 1
|
||||||
|
ip = nil
|
||||||
|
while ip.nil?
|
||||||
|
sleep(ip_loop_delay)
|
||||||
|
ip = vm_object.guest_ip
|
||||||
|
unless ip_maxloop == 0
|
||||||
|
break if ip_loop_count >= ip_maxloop
|
||||||
|
|
||||||
|
ip_loop_count += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
{
|
{
|
||||||
'name' => vm_object.name,
|
'name' => vm_object.name,
|
||||||
'hostname' => hostname,
|
'hostname' => hostname,
|
||||||
'template' => pool_configuration['template'],
|
'template' => pool_configuration['template'],
|
||||||
'poolname' => pool_name,
|
'poolname' => pool_name,
|
||||||
'boottime' => boottime,
|
'boottime' => boottime,
|
||||||
'powerstate' => powerstate
|
'powerstate' => powerstate,
|
||||||
|
'ip' => ip
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -198,13 +198,24 @@ MockVirtualDiskManager = Object
|
||||||
MockVirtualMachine = Struct.new(
|
MockVirtualMachine = Struct.new(
|
||||||
# https://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/vim.VirtualMachine.html
|
# https://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/vim.VirtualMachine.html
|
||||||
# From VirtualMachine
|
# From VirtualMachine
|
||||||
:config, :runtime, :snapshot, :summary,
|
:config, :runtime, :snapshot, :summary, :guest,
|
||||||
# From ManagedEntity
|
# From ManagedEntity
|
||||||
:name,
|
:name,
|
||||||
# From RbVmomi::VIM::ManagedEntity
|
# From RbVmomi::VIM::ManagedEntity
|
||||||
# https://github.com/vmware/rbvmomi/blob/master/lib/rbvmomi/vim/ManagedEntity.rb
|
# https://github.com/vmware/rbvmomi/blob/master/lib/rbvmomi/vim/ManagedEntity.rb
|
||||||
:path
|
:path
|
||||||
)
|
) do
|
||||||
|
# From RbVmomi::VIM::VirtualMachine
|
||||||
|
# https://github.com/ManageIQ/rbvmomi2/blob/59a5904031a0d7558f306e8d2a05001f9b6822de/lib/rbvmomi/vim/VirtualMachine.rb#L20
|
||||||
|
def guest_ip
|
||||||
|
g = self.guest
|
||||||
|
if g.ipAddress
|
||||||
|
g.ipAddress
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
MockVirtualMachineSnapshot = Struct.new(
|
MockVirtualMachineSnapshot = Struct.new(
|
||||||
# https://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/vim.vm.Snapshot.html
|
# https://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/vim.vm.Snapshot.html
|
||||||
|
|
@ -347,6 +358,12 @@ MockVirtualMachineGuestSummary = Struct.new(
|
||||||
:hostName
|
:hostName
|
||||||
)
|
)
|
||||||
|
|
||||||
|
MockVirtualMachineGuestInfo = Struct.new(
|
||||||
|
# https://developer.vmware.com/apis/1311/vsphere
|
||||||
|
# From Data Object - GuestInfo(vim.vm.GuestInfo)
|
||||||
|
:ipAddress
|
||||||
|
)
|
||||||
|
|
||||||
MockVirtualMachineRuntimeInfo = Struct.new(
|
MockVirtualMachineRuntimeInfo = Struct.new(
|
||||||
# https://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/vim.vm.RuntimeInfo.html
|
# https://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/vim.vm.RuntimeInfo.html
|
||||||
# From VirtualMachineRuntimeInfo
|
# From VirtualMachineRuntimeInfo
|
||||||
|
|
@ -801,6 +818,7 @@ end
|
||||||
def mock_RbVmomi_VIM_VirtualMachine(options = {})
|
def mock_RbVmomi_VIM_VirtualMachine(options = {})
|
||||||
options[:snapshot_tree] = nil if options[:snapshot_tree].nil?
|
options[:snapshot_tree] = nil if options[:snapshot_tree].nil?
|
||||||
options[:name] = 'VM' + rand(65536).to_s if options[:name].nil?
|
options[:name] = 'VM' + rand(65536).to_s if options[:name].nil?
|
||||||
|
options[:ip] = '169.254.255.255' if options[:ip].nil?
|
||||||
options[:path] = [] if options[:path].nil?
|
options[:path] = [] if options[:path].nil?
|
||||||
|
|
||||||
mock = MockVirtualMachine.new()
|
mock = MockVirtualMachine.new()
|
||||||
|
|
@ -810,11 +828,13 @@ def mock_RbVmomi_VIM_VirtualMachine(options = {})
|
||||||
mock.summary.runtime = MockVirtualMachineRuntimeInfo.new()
|
mock.summary.runtime = MockVirtualMachineRuntimeInfo.new()
|
||||||
mock.summary.guest = MockVirtualMachineGuestSummary.new()
|
mock.summary.guest = MockVirtualMachineGuestSummary.new()
|
||||||
mock.runtime = mock.summary.runtime
|
mock.runtime = mock.summary.runtime
|
||||||
|
mock.guest = MockVirtualMachineGuestInfo.new()
|
||||||
|
|
||||||
mock.name = options[:name]
|
mock.name = options[:name]
|
||||||
mock.summary.guest.hostName = options[:hostname]
|
mock.summary.guest.hostName = options[:hostname]
|
||||||
mock.runtime.bootTime = options[:boottime]
|
mock.runtime.bootTime = options[:boottime]
|
||||||
mock.runtime.powerState = options[:powerstate]
|
mock.runtime.powerState = options[:powerstate]
|
||||||
|
mock.guest.ipAddress = options[:ip]
|
||||||
|
|
||||||
unless options[:snapshot_tree].nil?
|
unless options[:snapshot_tree].nil?
|
||||||
mock.snapshot = MockVirtualMachineSnapshotInfo.new()
|
mock.snapshot = MockVirtualMachineSnapshotInfo.new()
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -50,6 +50,11 @@ describe 'Vmpooler::PoolManager::Provider::VSphere' do
|
||||||
:config:
|
:config:
|
||||||
max_tries: 3
|
max_tries: 3
|
||||||
retry_factor: 10
|
retry_factor: 10
|
||||||
|
:dns_configs:
|
||||||
|
:gcp-clouddns:
|
||||||
|
project: vmpooler-test
|
||||||
|
domain: vmpooler.example.com
|
||||||
|
dns_zone_resource_name: vmpooler-example-com
|
||||||
:providers:
|
:providers:
|
||||||
:vsphere:
|
:vsphere:
|
||||||
server: "vcenter.domain.local"
|
server: "vcenter.domain.local"
|
||||||
|
|
@ -71,6 +76,7 @@ describe 'Vmpooler::PoolManager::Provider::VSphere' do
|
||||||
ready_ttl: 1440
|
ready_ttl: 1440
|
||||||
clone_target: 'cluster1'
|
clone_target: 'cluster1'
|
||||||
provider: 'vsphere'
|
provider: 'vsphere'
|
||||||
|
dns_config: 'gcp-clouddns'
|
||||||
EOT
|
EOT
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -535,7 +541,7 @@ EOT
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when VM exists but is missing information' do
|
context 'when VM exists but is missing hostname, boottime, powerstate' do
|
||||||
let(:vm_object) { mock_RbVmomi_VIM_VirtualMachine({
|
let(:vm_object) { mock_RbVmomi_VIM_VirtualMachine({
|
||||||
:name => vmname,
|
:name => vmname,
|
||||||
})
|
})
|
||||||
|
|
@ -560,10 +566,25 @@ EOT
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when VM exists but is missing ip' do
|
||||||
|
let(:vm_object) { mock_RbVmomi_VIM_VirtualMachine({
|
||||||
|
:name => vmname,
|
||||||
|
:ip => '',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
it 'should return empty for ip' do
|
||||||
|
result = subject.get_vm(poolname,vmname)
|
||||||
|
|
||||||
|
expect(result['ip']).to eq('')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'when VM exists and contains all information' do
|
context 'when VM exists and contains all information' do
|
||||||
let(:vm_hostname) { "#{vmname}.demo.local" }
|
let(:vm_hostname) { "#{vmname}.demo.local" }
|
||||||
let(:boot_time) { Time.now }
|
let(:boot_time) { Time.now }
|
||||||
let(:power_state) { 'MockPowerState' }
|
let(:power_state) { 'MockPowerState' }
|
||||||
|
let(:ip) { '169.254.255.255' }
|
||||||
|
|
||||||
let(:vm_object) { mock_RbVmomi_VIM_VirtualMachine({
|
let(:vm_object) { mock_RbVmomi_VIM_VirtualMachine({
|
||||||
:name => vmname,
|
:name => vmname,
|
||||||
|
|
@ -622,6 +643,11 @@ EOT
|
||||||
expect(result['powerstate']).to eq(power_state)
|
expect(result['powerstate']).to eq(power_state)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'should return the ip' do
|
||||||
|
result = subject.get_vm(poolname,vmname)
|
||||||
|
|
||||||
|
expect(result['ip']).to eq(ip)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -1056,9 +1082,10 @@ EOT
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#vm_ready?' do
|
describe '#vm_ready?' do
|
||||||
let(:domain) { nil }
|
let(:domain) { 'vmpooler.example.com' }
|
||||||
context 'When a VM is ready' do
|
context 'When a VM is ready' do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
|
allow(subject).to receive(:domain).and_return('vmpooler.example.com')
|
||||||
expect(subject).to receive(:open_socket).with(vmname, domain)
|
expect(subject).to receive(:open_socket).with(vmname, domain)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -1075,6 +1102,7 @@ EOT
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should return true' do
|
it 'should return true' do
|
||||||
|
allow(subject).to receive(:domain).and_return('vmpooler.example.com')
|
||||||
expect(subject.vm_ready?('missing_pool',vmname)).to be true
|
expect(subject.vm_ready?('missing_pool',vmname)).to be true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -1390,7 +1418,7 @@ EOT
|
||||||
let(:TCPSocket) { double('tcpsocket') }
|
let(:TCPSocket) { double('tcpsocket') }
|
||||||
let(:socket) { double('tcpsocket') }
|
let(:socket) { double('tcpsocket') }
|
||||||
let(:hostname) { 'host' }
|
let(:hostname) { 'host' }
|
||||||
let(:domain) { 'domain.local'}
|
let(:domain) { 'vmpooler.example.com' }
|
||||||
let(:default_socket) { 22 }
|
let(:default_socket) { 22 }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ Gem::Specification.new do |s|
|
||||||
s.files = Dir[ "lib/**/*" ]
|
s.files = Dir[ "lib/**/*" ]
|
||||||
s.require_paths = ["lib"]
|
s.require_paths = ["lib"]
|
||||||
s.add_dependency 'rbvmomi2', '>= 3.1', '< 4.0'
|
s.add_dependency 'rbvmomi2', '>= 3.1', '< 4.0'
|
||||||
s.add_dependency 'vmpooler', '~> 2.4'
|
s.add_dependency 'vmpooler', '~> 3.0'
|
||||||
|
|
||||||
# Testing dependencies
|
# Testing dependencies
|
||||||
s.add_development_dependency 'climate_control', '>= 0.2.0'
|
s.add_development_dependency 'climate_control', '>= 0.2.0'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue