console-launcher 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/bin/console-launcher +257 -0
  2. metadata +51 -0
@@ -0,0 +1,257 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright 2013 Red Hat Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # This script calls the RHEV-M Virt API and creates callable cmd-lines
18
+ # to the remote viewer.
19
+ #
20
+ # written by:
21
+ # Juergen Hoffmann <buddy@redhat.com>
22
+ # Thomas Crowe <tcrowe@redhat.com>
23
+ # Vinny Valdez <vvaldez@redhat.com>
24
+ #
25
+ # May 14, 2013
26
+ # - initial version
27
+ #
28
+ # May 22, 2013
29
+ # - Made sure to strip http and https from the host definition
30
+
31
+ require 'rubygems'
32
+ require 'rest_client'
33
+ require 'xmlsimple'
34
+ require 'optparse'
35
+ require 'tempfile' # required to download the certificate files on they fly
36
+ require 'net/http'
37
+ require 'highline/import' # Secure Password Prompting if a user does not provide it when the script is called
38
+
39
+ # queries the User for a password
40
+ def get_password(prompt="RHEV-M Password: ")
41
+ ask(prompt) {|q| q.echo = "*"}
42
+ end
43
+
44
+ def strip_url(url)
45
+ # Remove any leading http or https from the host
46
+ url = url.split("://")[1] if url.include? "://"
47
+ return url
48
+ end
49
+
50
+ @options = {}
51
+
52
+ optparse = OptionParser.new do |opts|
53
+ opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
54
+
55
+ @options[:print] = false
56
+ opts.on( '--print', 'Print the command to launch the Remote Viewer instead of executing it') do |directory|
57
+ @options[:print] = true
58
+ end
59
+
60
+ @options[:dryrun] = false
61
+ opts.on( '-d', '--dry-run', 'Do not execute the Remote Viewer Application') do |dryrun|
62
+ @options[:dryrun] = true
63
+ end
64
+
65
+ @options[:host] = nil
66
+ opts.on( '-h', '--host HOSTNAME', 'The Hostname of your RHEV-M Installation') do |host|
67
+ @options[:host] = strip_url(host)
68
+ end
69
+
70
+ @options[:user] = "admin@internal"
71
+ opts.on( '-u', '--username USERNAME', 'The Username used to establish the connection to --host (defaults to admin@internal)') do |u|
72
+ @options[:user] = u
73
+ end
74
+
75
+ @options[:pass] = nil
76
+ opts.on( '-p', '--password PASSWORD', 'The Password used to establish the connection to --host') do |pass|
77
+ @options[:pass] = pass
78
+ end
79
+
80
+ # This displays the help screen, all programs are
81
+ # assumed to have this option.
82
+ opts.on( '', '--help', 'Display this Help Message' ) do
83
+ puts ""
84
+ puts "This script connects to a RHEV-M Instance and lists all running VMs. You can choose which VM you want to"
85
+ puts "connect to via SPICE Protocol."
86
+ puts ""
87
+ puts "This script requires a working SPICE Client for your platform. You can get it from"
88
+ puts " - MacOSX: http://people.freedesktop.org/~teuf/spice-gtk-osx/dmg/0.3.1/"
89
+ puts " - Linux: TBD"
90
+ puts " - Windows: TBD"
91
+ puts ""
92
+ puts opts
93
+ exit
94
+ end
95
+ end
96
+
97
+ # Parse the command-line. Remember there are two forms
98
+ # of the parse method. The 'parse' method simply parses
99
+ # ARGV, while the 'parse!' method parses ARGV and removes
100
+ # any @options found there, as well as any parameters for
101
+ # the @options. What's left is the list of files to resize.
102
+ optparse.parse!
103
+
104
+ if @options[:host] == nil
105
+ puts "ERROR: You have to configure RHEV-M Hostname to connect to"
106
+ puts optparse.help
107
+ exit 1
108
+ end
109
+
110
+ @options[:pass] = get_password if @options[:pass] == nil
111
+
112
+ class VM
113
+ attr_accessor :id, :name, :description, :host_uuid, :state, :port, :secure_port, :address
114
+
115
+ def initialize(vm)
116
+ @id = vm['id']
117
+ @name = vm['name']
118
+ @description = vm['description']
119
+ @address = vm['display']['address'] unless vm['display'].nil?
120
+ @port = vm['display']['port'] unless vm['display'].nil?
121
+ @secure_port = vm['display']['secure_port'] unless vm['display'].nil?
122
+ @state = vm['status']['state'] unless vm['status'].nil?
123
+ @host_uuid = vm['host']['id'] unless vm['host'].nil?
124
+ end
125
+ end
126
+
127
+
128
+ # download the certificate file on the fly
129
+ begin
130
+ cert = Tempfile.new(@options[:host] + ".crt")
131
+ Net::HTTP.start(@options[:host]) do |http|
132
+ begin
133
+ http.request_get('/ca.crt') do |resp|
134
+ resp.read_body do |segment|
135
+ cert.write(segment)
136
+ end
137
+ end
138
+ ensure
139
+ cert.close()
140
+ end
141
+ end
142
+ @cert = cert.path
143
+ rescue => e
144
+ puts "There has been an error downloading the certificate file from #{@options[:host]}"
145
+ e.message
146
+ exit 1
147
+ end
148
+
149
+ # Create a little helper object that we will use to
150
+ # make connections to the REST API
151
+ @rhevm = RestClient::Resource.new(
152
+ "https://" + @options[:host],
153
+ :user => @options[:user],
154
+ :password => @options[:pass],
155
+ :ssl_ca_cert => @cert,
156
+ :ssl_version => "SSLv3",
157
+ :verify_ssl => OpenSSL::SSL::VERIFY_NONE)
158
+
159
+ def get_vms(vms_data)
160
+ # Iterate through the VM's and get all the
161
+ # required information
162
+ @vms = Array.new # Clear out array
163
+ vms_data['vm'].each do |vm|
164
+ # Making sure we only consider VM's that are in state up (so they do have a console to connect to)
165
+ # and that have the spice protocol enabled as the connection mode
166
+ if vm['status']['state'] == "up" && vm['display']['type'] == "spice"
167
+ @vms.push(VM.new(vm))
168
+ end
169
+ end
170
+ return @vms
171
+ end
172
+
173
+ def launch_viewer(index)
174
+ vm = @vms[index-1]
175
+
176
+ # let us no gather the host subject
177
+ hosts_data = XmlSimple.xml_in(@rhevm["/api/hosts/"+vm.host_uuid].get.body, { 'ForceArray' => false })
178
+ host_subject = hosts_data['certificate']['subject']
179
+
180
+ ticket_data = XmlSimple.xml_in(@rhevm["/api/vms/" + vm.id + "/ticket"].post("<action><ticket><expiry>300</expiry></ticket></action>", :content_type => 'application/xml').body, { 'ForceArray' => false })
181
+ password = ticket_data['ticket']['value']
182
+
183
+ # Creating the .vv File for the connection
184
+ # download the certificate file on the fly
185
+ vv = Tempfile.new("#{vm.name}.vv")
186
+ begin
187
+ vv.puts("[virt-viewer]")
188
+ vv.puts("type=spice")
189
+ vv.puts("host=#{vm.address}")
190
+ vv.puts("port=#{vm.port}")
191
+ vv.puts("password=#{password}")
192
+ vv.puts("tls-port=#{vm.secure_port}")
193
+ vv.puts("fullscreen=0")
194
+ vv.puts("title=vm:#{vm.name} - %d - Press SHIFT+F12 to Release Cursor")
195
+ vv.puts("enable-smartcard=0")
196
+ vv.puts("enable-usb-autoshare=1")
197
+ vv.puts("usb-filter=-1,-1,-1,-1,0")
198
+ vv.puts("host-subject=#{host_subject}")
199
+ vv.puts("toggle-fullscreen=shift+f11")
200
+ vv.puts("release-cursor=shift+f12")
201
+ ensure
202
+ vv.close()
203
+ end
204
+
205
+ # Now that we have all the information we can print the cmd line
206
+ puts "Console to VM: #{vm.name} state: #{vm.state} is started"
207
+ command = "/Applications/RemoteViewer.app/Contents/MacOS/RemoteViewer --spice-ca-file #{@cert} #{vv.path}"
208
+ puts command if @options[:print]
209
+ unless @options[:dryrun]
210
+ (pid = fork) ? Process.detach(pid) : exec(command)
211
+ end
212
+ puts "Reloading Virtual Machines Selection Menu ..."
213
+ sleep(5)
214
+ end
215
+
216
+ while true do
217
+ begin
218
+ @vms = Array.new # Clear out array
219
+ # get the vms api and get the list of vms
220
+ vms_data = XmlSimple.xml_in(@rhevm["/api/vms"].get.body, { 'ForceArray' => false })
221
+ @vms = get_vms(vms_data)
222
+ # Print the selection to the User
223
+ puts
224
+ puts "Running Virtual Machines found for #{@options[:host]}:"
225
+ @vms.each_with_index do |v, index|
226
+ puts "#{index+1}. Name: #{v.name} Description: #{v.description} State: #{v.state}"
227
+ end
228
+ puts
229
+ puts "r. Refresh"
230
+ puts "q. Quit"
231
+ puts
232
+
233
+ puts "Please select the VM you wish to open: "
234
+
235
+ STDOUT.flush
236
+ index = gets.chomp # Hackish, just wanting to add quit
237
+ if index.to_s == "q"
238
+ exit 0
239
+ elsif index.to_s == "r"
240
+ next
241
+ end
242
+ index = index.to_i
243
+ if (1..@vms.size).member?(index)
244
+ launch_viewer(index)
245
+ else
246
+ puts "ERROR: Your selection #{index} is out of range."
247
+ end
248
+ rescue => e
249
+ puts "There was an error retrieving the Virtual Machines from #{@options[:host]}: #{e.message}"
250
+ puts e.backtrace
251
+ exit 1
252
+ end
253
+ end
254
+
255
+ exit 0
256
+
257
+
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: console-launcher
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Juergen Hoffmann
9
+ - Vinny Valdez
10
+ - Thomas Crowe
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2013-05-23 00:00:00.000000000 Z
15
+ dependencies: []
16
+ description: This gem provides the ability to launch console sessions on Mac
17
+ email:
18
+ - buddy@redhat.com
19
+ - vvaldez@redhat.com
20
+ - tcrowe@redhat.com
21
+ executables:
22
+ - console-launcher
23
+ extensions: []
24
+ extra_rdoc_files: []
25
+ files:
26
+ - bin/console-launcher
27
+ homepage: https://github.com/juhoffma/rhev-console-launcher
28
+ licenses: []
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ requirements: []
46
+ rubyforge_project:
47
+ rubygems_version: 1.8.24
48
+ signing_key:
49
+ specification_version: 3
50
+ summary: RHEV-M Console Launcher
51
+ test_files: []