Skip to content

Commit

Permalink
Merge pull request #218 from miha-plesko/console-access
Browse files Browse the repository at this point in the history
Add support for vCloud console access via WebMKS
(cherry picked from commit db12e68)

https://bugzilla.redhat.com/show_bug.cgi?id=1563364
  • Loading branch information
agrare authored and simaishi committed Apr 3, 2018
1 parent a7c376f commit afe4151
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 0 deletions.
1 change: 1 addition & 0 deletions app/models/manageiq/providers/vmware/cloud_manager/vm.rb
@@ -1,5 +1,6 @@
class ManageIQ::Providers::Vmware::CloudManager::Vm < ManageIQ::Providers::CloudManager::Vm
include_concern 'Operations'
include_concern 'RemoteConsole'

supports :snapshots
supports :remove_all_snapshots
Expand Down
@@ -0,0 +1,75 @@
module ManageIQ::Providers::Vmware::CloudManager::Vm::RemoteConsole
require_dependency 'securerandom'

def console_supported?(type)
%w(WEBMKS).include?(type.upcase)
end

def validate_remote_console_acquire_ticket(protocol, options = {})
raise(MiqException::RemoteConsoleNotSupportedError, "#{protocol} remote console requires the vm to be registered with a management system.") if ext_management_system.nil?
options[:check_if_running] = true unless options.key?(:check_if_running)
raise(MiqException::RemoteConsoleNotSupportedError, "#{protocol} remote console requires the vm to be running.") if options[:check_if_running] && state != "on"
end

def remote_console_acquire_ticket(userid, originating_server, protocol)
send("remote_console_#{protocol.to_s.downcase}_acquire_ticket", userid, originating_server)
end

def remote_console_acquire_ticket_queue(protocol, userid)
task_opts = {
:action => "Acquiring Vm #{name} #{protocol.to_s.upcase} remote console ticket for user #{userid}",
:userid => userid
}

queue_opts = {
:class_name => self.class.name,
:instance_id => id,
:method_name => 'remote_console_acquire_ticket',
:priority => MiqQueue::HIGH_PRIORITY,
:role => 'ems_operations',
:zone => my_zone,
:args => [userid, MiqServer.my_server.id, protocol]
}

MiqTask.generic_action_with_callback(task_opts, queue_opts)
end

#
# WebMKS
#

def remote_console_webmks_acquire_ticket(userid, originating_server = nil)
validate_remote_console_webmks_support
ticket = nil
ext_management_system.with_provider_connection do |service|
ticket = service.post_acquire_mks_ticket(ems_ref).body
end
raise(MiqException::RemoteConsoleNotSupportedError, 'Could not obtain WebMKS ticket') unless ticket && ticket[:Ticket]

SystemConsole.force_vm_invalid_token(id)

console_args = {
:user => User.find_by(:userid => userid),
:vm_id => id,
:ssl => true,
:protocol => 'webmks-uint8utf8',
:secret => ticket[:Ticket],
:url_secret => SecureRandom.hex,
:url => "/#{ticket[:Port]};#{ticket[:Ticket]}"
}
SystemConsole.launch_proxy_if_not_local(console_args, originating_server, ticket[:Host], 443).update(
:secret => 'is-in-url',
# vCloud specific querystring params
:is_vcloud => true,
:vmx => ticket[:Vmx]
)
end

def validate_remote_console_webmks_support
validate_remote_console_acquire_ticket('webmks')
if (api_version = ext_management_system.api_version.to_f) && api_version < 5.5
raise(MiqException::RemoteConsoleNotSupportedError, "vCloud version #{api_version} does not support WebMKS remote console.")
end
true
end
end
@@ -0,0 +1,98 @@
describe ManageIQ::Providers::Vmware::CloudManager::Vm::RemoteConsole do
let(:user) { FactoryGirl.create(:user) }
let(:ems) { FactoryGirl.create(:ems_vmware_cloud, :api_version => 5.5) }
let(:vm) { FactoryGirl.create(:vm_vcloud, :ext_management_system => ems, :raw_power_state => 'on') }

context '#remote_console_acquire_ticket' do
it 'with :webmks' do
expect(vm).to receive(:remote_console_webmks_acquire_ticket).with(user.userid, 1)
vm.remote_console_acquire_ticket(user.userid, 1, :webmks)
end
end

context '#remote_console_acquire_ticket_queue' do
let(:server) { double('MiqServer') }

before(:each) do
allow(vm).to receive_messages(:my_zone => nil)
allow(server).to receive_messages(:my_zone => nil)
allow(server).to receive_messages(:id => 1)
allow(MiqServer).to receive_messages(:my_server => server)
end

it 'with :webmks' do
vm.remote_console_acquire_ticket_queue(:webmks, user.userid)

q_all = MiqQueue.all
expect(q_all.length).to eq(1)
expect(q_all[0].method_name).to eq('remote_console_acquire_ticket')
expect(q_all[0].args).to eq([user.userid, 1, :webmks])
end
end

context '#remote_console_webmks_acquire_ticket' do
before(:each) do
allow(ems).to receive(:with_provider_connection).and_yield(connection)
allow(SecureRandom).to receive(:hex).and_return('hex')
end

let(:connection) { double('connection') }
let(:empty_response) { double('response', :body => {}) }
let(:response) do
double(
'response',
:body => {
:Ticket => 'ticket',
:Port => 1234,
:Host => 'host'
}
)
end

it 'performs validation' do
expect(connection).to receive(:post_acquire_mks_ticket).and_return(empty_response)
expect(vm).to receive(:validate_remote_console_webmks_support)
expect { vm.remote_console_webmks_acquire_ticket(user.userid) }.to raise_error MiqException::RemoteConsoleNotSupportedError
end

it 'launches proxy socket' do
expect(connection).to receive(:post_acquire_mks_ticket).and_return(response)
expect(SystemConsole).to receive(:launch_proxy_if_not_local).with(
{
:user => user,
:vm_id => vm.id,
:ssl => true,
:protocol => 'webmks-uint8utf8',
:secret => 'ticket',
:url_secret => 'hex',
:url => '/1234;ticket'
},
1, 'host', 443
).and_return({})
vm.remote_console_webmks_acquire_ticket(user.userid, 1)
end
end

context '#validate_remote_console_webmks_support' do
it 'normal case' do
ems.api_version = '5.5'
expect(vm.validate_remote_console_webmks_support).to be_truthy
end

it 'with vm with no ems' do
vm.ext_management_system = nil
vm.save!
expect { vm.validate_remote_console_webmks_support }.to raise_error MiqException::RemoteConsoleNotSupportedError
end

it 'with vm off' do
vm.raw_power_state = 'off'
expect { vm.validate_remote_console_webmks_support }.to raise_error MiqException::RemoteConsoleNotSupportedError
end

it 'on vCloud 5.1' do
ems.api_version = '5.1'
expect { vm.validate_remote_console_webmks_support }.to raise_error MiqException::RemoteConsoleNotSupportedError
end
end
end

0 comments on commit afe4151

Please sign in to comment.