Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support VM password from config + WinRM loop bug #181

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ GEM
erubis (2.7.0)
excon (0.62.0)
ffi (1.9.23)
ffi (1.9.23-x64-mingw32)
fission (0.5.0)
CFPropertyList (~> 2.2)
fog (2.0.0)
Expand Down Expand Up @@ -230,6 +231,8 @@ GEM
net-ssh (4.2.0)
nokogiri (1.8.2)
mini_portile2 (~> 2.3.0)
nokogiri (1.8.2-x64-mingw32)
mini_portile2 (~> 2.3.0)
nori (2.6.0)
rake (10.5.0)
rb-fsevent (0.10.3)
Expand Down Expand Up @@ -291,6 +294,7 @@ GEM

PLATFORMS
ruby
x64-mingw32

DEPENDENCIES
coveralls
Expand Down
14 changes: 6 additions & 8 deletions lib/vagrant-cloudstack/action/read_winrm_info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,13 @@ def read_winrm_info(cloudstack, machine)
# the username via winrm_info ... yet ;-)

# Read password from file into domain_config
if domain_config.vm_password.nil?
vmcredentials_file = machine.data_dir.join("vmcredentials")
if vmcredentials_file.file?
vmcredentials_password = nil
File.read(vmcredentials_file).each_line do |line|
vmcredentials_password = line.strip
end
domain_config.vm_password = vmcredentials_password
vmcredentials_file = machine.data_dir.join("vmcredentials")
if vmcredentials_file.file?
vmcredentials_password = nil
File.read(vmcredentials_file).each_line do |line|
vmcredentials_password = line.strip
end
domain_config.vm_password = vmcredentials_password
end

transport_info = transport_info.merge({
Expand Down
61 changes: 42 additions & 19 deletions lib/vagrant-cloudstack/action/run_instance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ def call(env)

store_volumes

store_password
password = wait_for_password

store_password(password)

configure_networking

Expand Down Expand Up @@ -381,6 +383,14 @@ def get_communicator_short_name(communicator)
communicator_short_names[communicator.class.name]
end

def get_communicator_connect_attempts(communicator)
communicator_connect_attempts = {
'VagrantPlugins::CommunicatorSSH::Communicator' => 40,
'VagrantPlugins::CommunicatorWinRM::Communicator' => 1
}
return communicator_connect_attempts[communicator.class.name].nil? ? 1 : communicator_connect_attempts[communicator.class.name]
end

def evaluate_pf_private_port
return unless @domain_config.pf_private_port.nil?

Expand Down Expand Up @@ -488,9 +498,8 @@ def apply_port_forwarding_rule(rule)
if response['queryasyncjobresultresponse']['jobstatus'] != 0
port_forwarding_rule = response['queryasyncjobresultresponse']['jobresult']['portforwardingrule']
break
else
sleep 2
end
sleep 2
end
rescue Fog::Compute::Cloudstack::Error => e
raise Errors::FogError, :message => e.message
Expand Down Expand Up @@ -717,9 +726,8 @@ def apply_firewall_rule(acl_name, options, response_string, type_string)
if response['queryasyncjobresultresponse']['jobstatus'] != 0
firewall_rule = response['queryasyncjobresultresponse']['jobresult'][type_string]
break
else
sleep 2
end
sleep 2
end
rescue Fog::Compute::Cloudstack::Error => e
if e.message =~ /The range specified,.*conflicts with rule/
Expand Down Expand Up @@ -756,35 +764,47 @@ def generate_ssh_keypair(keyname, account = nil, domainid = nil, projectid = nil
@domain_config.keypair = sshkeypair['name']
end

def store_password
def wait_for_password
password = nil
if @server.password_enabled and @server.respond_to?('job_id')

if @server.respond_to?('job_id')
server_job_result = @env[:cloudstack_compute].query_async_job_result({:jobid => @server.job_id})
if server_job_result.nil?
@env[:ui].warn(' -- Failed to retrieve job_result for retrieving the password')
return
raise 'ERROR -- Failed to retrieve job_result'
end

while true
server_job_result = @env[:cloudstack_compute].query_async_job_result({:jobid => @server.job_id})
if server_job_result['queryasyncjobresultresponse']['jobstatus'] != 0
password = server_job_result['queryasyncjobresultresponse']['jobresult']['virtualmachine']['password']
break
else
sleep 2
end
sleep 2
end

@env[:ui].info("Password of virtualmachine: #{password}")
# Set the password on the current communicator
@domain_config.vm_password = password
end

# Save password to file
vmcredentials_file = @env[:machine].data_dir.join('vmcredentials')
vmcredentials_file.open('w') do |f|
f.write("#{password}")
end
password
end

def store_password(password)
unless @server.password_enabled
@env[:ui].info("VM is not password-enabled. Using virtualmachine password from config")
if @domain_config.vm_password.nil?
fail "No vm_password configured but VM is not password enabled either!"
end
password = @domain_config.vm_password
end

# Save password to file
vmcredentials_file = @env[:machine].data_dir.join('vmcredentials')
vmcredentials_file.open('w') do |f|
f.write("#{password}")
end

# Set the password on the current communicator
@domain_config.vm_password = password
end

def store_volumes
Expand Down Expand Up @@ -829,15 +849,18 @@ def wait_for_communicator_ready
@env[:metrics]['instance_ssh_time'] = Util::Timer.time do
# Wait for communicator to be ready.
communicator_short_name = get_communicator_short_name(@env[:machine].communicate)
communicator_connect_attempts = get_communicator_connect_attempts(@env[:machine].communicate)
@env[:ui].info(
I18n.t('vagrant_cloudstack.waiting_for_communicator',
communicator: communicator_short_name.to_s.upcase)
)
while true
connection_attempt = 0
while connection_attempt<communicator_connect_attempts
# If we're interrupted then just back out
break if @env[:interrupted]
break if @env[:machine].communicate.ready?
sleep 2
connection_attempt = connection_attempt + 1
end
end
@logger.info("Time for SSH ready: #{@env[:metrics]['instance_ssh_time']}")
Expand Down
22 changes: 12 additions & 10 deletions spec/vagrant-cloudstack/action/run_instance_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,11 @@

allow(machine).to receive(:provider_config).and_return(provider_config)
expect(server).to receive(:wait_for).and_return(ready = true)
allow(server).to receive(:password_enabled).and_return(false)
allow(server).to receive(:password_enabled).and_return(true)
allow(server).to receive(:job_id).and_return(JOB_ID)

expect(file).to receive(:write).with(GENERATED_PASSWORD)
allow(cloudstack_compute).to receive(:query_async_job_result).with(jobid: JOB_ID).and_return(fake_job_result)
expect(cloudstack_compute).to receive(:servers).and_return(servers)
allow(cloudstack_compute).to receive(:send).with(:list_zones, available: true).and_return(list_zones_response)
allow(cloudstack_compute).to receive(:send).with(:list_service_offerings, listall: true)
Expand Down Expand Up @@ -289,6 +293,7 @@
cfg.ssh_key = ssh_key
cfg.security_groups = security_groups
cfg.network_name = network_name
cfg.vm_password = GENERATED_PASSWORD
end
config.finalize!
config.get_domain_config(:cloudstack)
Expand Down Expand Up @@ -354,8 +359,8 @@
should eq true
end
end
end

end
context 'in advanced zone' do
let(:pf_ip_address) { nil }
let(:pf_trusted_networks) { nil }
Expand All @@ -377,6 +382,7 @@
cfg.pf_open_firewall = pf_open_firewall
cfg.ssh_key = ssh_key
cfg.disk_offering_name = disk_offering_name
cfg.vm_password = GENERATED_PASSWORD
end
config.finalize!
config.get_domain_config(:cloudstack)
Expand All @@ -385,8 +391,6 @@
let(:winrm_config) { double('VagrantPlugins::VagrantWinRM::WinRMConfig') }

before(:each) do
allow(cloudstack_compute).to receive(:query_async_job_result).with(jobid: JOB_ID).and_return(fake_job_result)

allow(cloudstack_compute).to receive(:send).with(:list_networks, {}).and_return(list_networks_response)
end

Expand Down Expand Up @@ -427,11 +431,9 @@
end
end

context 'with generated password' do
context 'with static password' do
before(:each) do
expect(server).to receive(:password_enabled).and_return(true)
allow(server).to receive(:job_id).and_return(JOB_ID)
expect(file).to receive(:write).with(GENERATED_PASSWORD)
expect(server).to receive(:password_enabled).and_return(false)
end

it 'starts a vm' do
Expand Down Expand Up @@ -606,4 +608,4 @@
end
end
end
end
end