console-launcher 0.0.8 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NzdlYmU5NTgzZmI5NTlmYzdhYmZiYmQ2OGMwNzQ3MmRmNDA2YjkzNg==
4
+ NTU4NDAyMmFiMTAwNDZjYjNiODRkMTRmODg1MDcxOGFhZjNhYjFkMg==
5
5
  data.tar.gz: !binary |-
6
- MDU4Y2JlNmIxODI1OGE4ODE3Njg2NzJiNzg3OGFmZjFjODA3ZDU5Yw==
6
+ YjQ2ODFhMWNjZWIwNTg3ZjQ0MzIyMmRkNjFjMWJhZTFlNDIxODk5ZQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- YmE0YTFkMWRjZGQ4NjUwZTkzYzcxOWYyYWQ3NTE1ZDY0MTVjMWUyNTJmNjFk
10
- ZmM5MmM1MTZkN2M5NWE3MDVhZTg2NzIyZDZmZWM3OTZiMjZkNzlkNTc0YWZm
11
- ZTUyN2M0NTU2N2ZiMTEyZmFlNjFkZWJiZDk4YWU2Yjg2YjhmNWM=
9
+ MTQ4MDA2ZjEwZDAyZWJmZDMyYzgxMDliNGVkZDNjOWYwOGMzNWNmMmM1Y2U0
10
+ ZjdjYmU2MGEzYzc4ZDZiNDI0OWRjYjVjZTkyMjRmYzMzZDViYmFjZTFiNzFk
11
+ MzkxZmEzZjcyMDNmNjJlMTlmMWUyODExYTQ5ZjhmNTg0NmE4Njc=
12
12
  data.tar.gz: !binary |-
13
- ZGUzYmM3NTRhNTVlYmJlYWI4NjQwZDMxY2Q5YmQ1YzZlYzMzNGQwZGYyYzY3
14
- ZDgyYjIyNjBiMTUzZTZkMThjODg5YzVmZDdjN2FjMjQ3NWRlYTlkMTE2ZTli
15
- ZDJmNGFlMTc3NTNjMDdlZmM3ZGY1MTI3YjY1MTFhZDI0NmVkMDk=
13
+ ZWYzM2U2ZWFjZDlkMWQ3MjhjMWM4MDBjOWE5OTg1ODIxZmU1YTA3MTQ2NzIx
14
+ ZTE2YzE2NzgxN2Y5MzkyMjI0ZGVmMzZlNTYwNmQyODhkNjYzZTMwYzM4Y2M4
15
+ Zjg5NTUwMDc0ZmQ5ODdkYWVlY2JjZWM3ZDIyYjBkNGRmMWRiN2M=
@@ -35,45 +35,30 @@ require 'optparse'
35
35
  require 'yaml'
36
36
  include Helper
37
37
 
38
- options = {
39
- print: false,
40
- dryrun: false,
41
- host: nil,
42
- user: "admin@internal",
43
- pass: nil
44
- }
45
-
46
- CONFIG_FILE = File.join(ENV['HOME'], '.config-launcher.rc.yaml')
47
- if File.exists? CONFIG_FILE
48
- config_options = YAML.load_file(CONFIG_FILE)
49
- options.merge!(config_options)
50
- else
51
- File.open(CONFIG_FILE, 'w') { |file| YAML::dump(options, file) }
52
- STDERR.puts "Initialized configuration file in #{CONFIG_FILE}"
53
- end
38
+ Helper.load_options
54
39
 
55
40
  optparse = OptionParser.new do |opts|
56
41
  opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
57
42
 
58
43
 
59
44
  opts.on('--print', 'Print the command that is called to launch the Console Session') do
60
- options[:print] = true
45
+ Helper::OPTIONS[:print] = true
61
46
  end
62
47
 
63
48
  opts.on('-d', '--dry-run', 'Do not execute the Remote Viewer Application') do
64
- options[:dryrun] = true
49
+ Helper::OPTIONS[:dryrun] = true
65
50
  end
66
51
 
67
52
  opts.on('-h', '--host HOSTNAME', 'The Hostname of your RHEV-M Installation') do |host|
68
- options[:host] = strip_url(host)
53
+ Helper::OPTIONS[:host] = strip_url(host)
69
54
  end
70
55
 
71
56
  opts.on('-u', '--username USERNAME', 'The Username used to establish the connection to --host (defaults to admin@internal)') do |u|
72
- options[:user] = u
57
+ Helper::OPTIONS[:user] = u
73
58
  end
74
59
 
75
60
  opts.on('-p', '--password PASSWORD', 'The Password used to establish the connection to --host') do |pass|
76
- options[:pass] = pass
61
+ Helper::OPTIONS[:pass] = pass
77
62
  end
78
63
 
79
64
  # This displays the help screen, all programs are
@@ -102,15 +87,15 @@ end
102
87
  # the @options. What's left is the list of files to resize.
103
88
  optparse.parse!
104
89
 
105
- if options[:host] == nil
90
+ if Helper::OPTIONS[:host] == nil
106
91
  puts "ERROR: You have to configure RHEV-M Hostname to connect to"
107
92
  puts optparse.help
108
93
  exit 1
109
94
  end
110
95
 
111
- options[:pass] = get_password() if options[:pass] == nil
96
+ Helper::OPTIONS[:pass] = get_password() if Helper::OPTIONS[:pass] == nil
112
97
 
113
- rhevm = RhevManager.new(options[:host], options[:user], options[:pass])
98
+ rhevm = RhevManager.new(Helper::OPTIONS[:host], Helper::OPTIONS[:user], Helper::OPTIONS[:pass])
114
99
 
115
100
  while true do
116
101
  begin
@@ -118,7 +103,7 @@ while true do
118
103
 
119
104
  # Print the selection to the User
120
105
  puts
121
- puts "Running Virtual Machines found for #{options[:host]}:"
106
+ puts "Running Virtual Machines found for #{Helper::OPTIONS[:host]}:"
122
107
  vms.each_with_index do |v, index|
123
108
  puts "#{index+1}. Name: #{v.name} Description: #{v.description} State: #{v.state}"
124
109
  end
@@ -140,8 +125,8 @@ while true do
140
125
 
141
126
  if (1..vms.size).member?(index)
142
127
  command = rhevm.launch_viewer(index)
143
- puts command if options[:print]
144
- unless options[:dryrun]
128
+ puts command if Helper::OPTIONS[:print]
129
+ unless Helper::OPTIONS[:dryrun]
145
130
  pid = Process.fork
146
131
 
147
132
  if pid.nil?
@@ -12,6 +12,12 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ # Author:: Juergen Hoffmann (mailto:buddy@redhat.com)
16
+ # Author:: Vinny Valdez (mailto:vvaldez@redhat.com)
17
+ # Author:: Thomas Crowe (mailto:tcrowe@redhat.com)
18
+ # Copyright:: Copyright (c) 2013 Red Hat Inc.
19
+ # License:: http://www.apache.org/licenses/LICENSE-2.0
20
+
15
21
  require 'rubygems'
16
22
  require 'rest_client'
17
23
  require 'xmlsimple'
@@ -19,121 +25,168 @@ require 'tmpdir' # required to download the certificate files on they fly
19
25
  require 'net/http'
20
26
  require 'highline/import' # Secure Password Prompting if a user does not provide it when the script is called
21
27
  require 'rhev-manager/virtual-machine'
28
+ require 'rbconfig'
29
+
30
+ # This class provides utility methods to encapsulates RESTful access to the RHEV Manager.
31
+ # Since the returned response is in XML this class transforms the XML Response into Ruby Objects.
32
+
33
+ class RhevManager
34
+
35
+ TMP_DIR = Dir.tmpdir
36
+
37
+ def initialize(host, user, password)
38
+ @host = host
39
+ @user = user
40
+ @pass = password
41
+
42
+ # Create a little helper object that we will use to
43
+ # make connections to the REST API
44
+ @rhevm = RestClient::Resource.new(
45
+ "https://" + @host,
46
+ :user => @user,
47
+ :password => @pass,
48
+ :ssl_ca_cert => @cert,
49
+ :ssl_version => "SSLv3",
50
+ :verify_ssl => OpenSSL::SSL::VERIFY_NONE)
51
+ get_cert
52
+ end
22
53
 
23
- class RhevManager
24
-
25
- TMP_DIR = Dir.tmpdir
26
-
27
- def initialize(host, user, password)
28
- @host = host
29
- @user = user
30
- @pass = password
31
-
32
- # Create a little helper object that we will use to
33
- # make connections to the REST API
34
- @rhevm = RestClient::Resource.new(
35
- "https://" + @host,
36
- :user => @user,
37
- :password => @pass,
38
- :ssl_ca_cert => @cert,
39
- :ssl_version => "SSLv3",
40
- :verify_ssl => OpenSSL::SSL::VERIFY_NONE)
41
- get_cert
42
- end
43
-
44
- def get_cert()
45
- # download the certificate file on the fly
46
- begin
47
- cert = File.new(TMP_DIR + "/" + @host + ".crt", "w+")
48
- Net::HTTP.start(@host) do |http|
49
- begin
50
- http.request_get('/ca.crt') do |resp|
51
- resp.read_body do |segment|
52
- cert.write(segment)
53
- end
54
+ # Download the Server SSL Certificate file on the fly
55
+ def get_cert()
56
+ begin
57
+ cert = File.new(TMP_DIR + "/" + @host + ".crt", "w+")
58
+ Net::HTTP.start(@host) do |http|
59
+ begin
60
+ http.request_get('/ca.crt') do |resp|
61
+ resp.read_body do |segment|
62
+ cert.write(segment)
54
63
  end
55
- ensure
56
- cert.close()
57
64
  end
65
+ ensure
66
+ cert.close()
58
67
  end
59
- @cert = cert.path
60
- rescue => e
61
- raise "There has been an error downloading the certificate file from #{@host}: #{e.message}"
62
68
  end
69
+ @cert = cert.path
70
+ rescue => e
71
+ raise "There has been an error downloading the certificate file from #{@host}: #{e.message}"
63
72
  end
73
+ end
64
74
 
65
- def get_vms()
66
- @vms = Array.new # Clear out array
67
- # get the vms api and get the list of vms
68
- vms_data = XmlSimple.xml_in(@rhevm["/api/vms"].get.body, {'ForceArray' => false})
69
-
70
- # Iterate through the VM's and get all the
71
- # required information
72
- vms_data['vm'].each do |vm|
73
- # Making sure we only consider VM's that are in state up (so they do have a console to connect to)
74
- # and that have the spice protocol enabled as the connection mode
75
- if vm['status']['state'] == "up" && vm['display']['type'] == "spice"
76
- @vms.push(VirtualMachine.new(vm))
77
- end
78
- end
79
- return @vms
80
- end
75
+ # Returns an array of VirtualMachine ruby objects that are running on the RHEV Manager
81
76
 
82
- def launch_viewer(index)
83
- vm = @vms[index-1]
84
-
85
- # let us no gather the host subject
86
- hosts_data = XmlSimple.xml_in(@rhevm["/api/hosts/"+vm.host_uuid].get.body, {'ForceArray' => false})
87
- host_subject = hosts_data['certificate']['subject']
88
-
89
- ticket_data = XmlSimple.xml_in(@rhevm["/api/vms/" + vm.id + "/ticket"].post("<action><ticket><expiry>30</expiry></ticket></action>", :content_type => 'application/xml').body, {'ForceArray' => false})
90
- password = ticket_data['ticket']['value']
91
-
92
- # Creating the .vv File for the connection
93
- # download the certificate file on the fly
94
- @vv = File.new(TMP_DIR + "/" + vm.name + ".vv", "w+")
95
- begin
96
- @vv.puts("[virt-viewer]")
97
- @vv.puts("type=spice")
98
- @vv.puts("host=#{vm.address}")
99
- @vv.puts("port=#{vm.port}")
100
- @vv.puts("password=#{password}")
101
- @vv.puts("tls-port=#{vm.secure_port}")
102
- @vv.puts("fullscreen=0")
103
- @vv.puts("title=vm:#{vm.name} - %d - Press SHIFT+F12 to Release Cursor")
104
- @vv.puts("enable-smartcard=0")
105
- @vv.puts("enable-usb-autoshare=1")
106
- @vv.puts("usb-filter=-1,-1,-1,-1,0")
107
- @vv.puts("host-subject=#{host_subject}")
108
- @vv.puts("toggle-fullscreen=shift+f11")
109
- @vv.puts("release-cursor=shift+f12")
110
- ensure
111
- @vv.close()
112
- end
77
+ def get_vms()
78
+ @vms = Array.new # Clear out array
79
+
80
+ # get the vms api and get the list of vms
81
+ vms_data = XmlSimple.xml_in(@rhevm["/api/vms"].get.body, {'ForceArray' => false})
113
82
 
114
- # Now that we have all the information we can print the cmd line
115
- puts "Console to VM: #{vm.name} state: #{vm.state} is started"
83
+ # Iterate through the VM's and get all the
84
+ # required information
85
+ vms_data['vm'].each do |vm|
86
+ # Making sure we only consider VM's that are in state up (so they do have a console to connect to)
87
+ # and that have the spice protocol enabled as the connection mode
88
+ if vm['status']['state'] == "up" && vm['display']['type'] == "spice"
89
+ @vms.push(VirtualMachine.new(vm))
90
+ end
91
+ end
92
+ return @vms
93
+ end
116
94
 
117
- command = "/Applications/RemoteViewer.app/Contents/MacOS/RemoteViewer --spice-ca-file #{@cert} #{@vv.path}"
95
+ # This method takes an index that is used to query the VirtualMachine Array for the VM that is supposed to
96
+ # be started. It then queries the RHEV Manager for the correct subject and then requests a ticket for the
97
+ # console session.
98
+ # It then creates a .vv file that is used to be passed to the RemoteViewer Application. It returns the command
99
+ # to be launched because we fork the process and detach from the RemoteViewer process so we are able to launch
100
+ # more than one Console Session at once.
101
+ def launch_viewer(index)
102
+ vm = @vms[index-1]
103
+
104
+ # let us no gather the host subject
105
+ hosts_data = XmlSimple.xml_in(@rhevm["/api/hosts/"+vm.host_uuid].get.body, {'ForceArray' => false})
106
+ host_subject = hosts_data['certificate']['subject']
107
+
108
+ ticket_data = XmlSimple.xml_in(@rhevm["/api/vms/" + vm.id + "/ticket"].post("<action><ticket><expiry>30</expiry></ticket></action>", :content_type => 'application/xml').body, {'ForceArray' => false})
109
+ password = ticket_data['ticket']['value']
110
+
111
+ # Creating the .vv File for the connection
112
+ # download the certificate file on the fly
113
+ @vv = File.new(TMP_DIR + "/" + vm.name + ".vv", "w+")
114
+ begin
115
+ @vv.puts("[virt-viewer]")
116
+ @vv.puts("type=spice")
117
+ @vv.puts("host=#{vm.address}")
118
+ @vv.puts("port=#{vm.port}")
119
+ @vv.puts("password=#{password}")
120
+ @vv.puts("tls-port=#{vm.secure_port}")
121
+ @vv.puts("fullscreen=0")
122
+ @vv.puts("title=vm:#{vm.name} - %d - Press SHIFT+F12 to Release Cursor")
123
+ @vv.puts("enable-smartcard=0")
124
+ @vv.puts("enable-usb-autoshare=1")
125
+ @vv.puts("usb-filter=-1,-1,-1,-1,0")
126
+ @vv.puts("host-subject=#{host_subject}")
127
+ @vv.puts("toggle-fullscreen=shift+f11")
128
+ @vv.puts("release-cursor=shift+f12")
129
+ ensure
130
+ @vv.close()
118
131
  end
119
132
 
133
+ # Now that we have all the information we can print the cmd line
134
+ puts "Console to VM: #{vm.name} state: #{vm.state} is started"
120
135
 
136
+ command = "#{Helper::OPTIONS[:viewer]} --spice-ca-file #{@cert} #{@vv.path}"
121
137
  end
122
138
 
139
+
140
+ end
141
+
123
142
  module Helper
124
143
 
144
+ CONFIG_FILE = File.join(ENV['HOME'], '.console-launcher.rc.yaml')
145
+
146
+ OPTIONS = {
147
+ print: false,
148
+ dryrun: false,
149
+ host: nil,
150
+ user: "admin@internal",
151
+ pass: nil
152
+ }
153
+
154
+ OPTIONS[:viewer] = case RbConfig::CONFIG['host_os']
155
+ when /mac|darwin/ then
156
+ "/Applications/RemoteViewer.app/Contents/MacOS/RemoteViewer"
157
+ when /linux|bsd|cygwin/ then
158
+ "/usr/bin/remote-viewer"
159
+ when /mswin|mingw/ then
160
+ "C:/Program Files/VirtViewer/bin/remote-viewer.exe"
161
+ # when /solaris|sunos/ then :Linux # needs testing..
162
+ else
163
+ raise "Your OS(#{ RbConfig::CONFIG['host_os'] }) is not yet supported"
164
+ end
165
+
166
+ def load_options
167
+ if File.exists? CONFIG_FILE
168
+ config_options = YAML.load_file(CONFIG_FILE)
169
+ OPTIONS.merge!(config_options)
170
+
171
+ unless config_options.has_key?(:viewer)
172
+ File.open(CONFIG_FILE, 'w') { |file| YAML::dump(OPTIONS, file) }
173
+ end
174
+ else
175
+ File.open(CONFIG_FILE, 'w') { |file| YAML::dump(OPTIONS, file) }
176
+ STDERR.puts "Initialized configuration file in #{CONFIG_FILE}"
177
+ end
178
+ end
179
+
125
180
  # queries the User for a password
126
181
  def get_password(prompt="RHEV-M Password: ")
127
182
  ask(prompt) { |q| q.echo = "*" }
128
183
  end
129
184
 
185
+ # Remove any leading http or https from the host
130
186
  def strip_url(url)
131
- # Remove any leading http or https from the host
132
187
  url = url.split("://")[1] if url.include? "://"
133
188
  return url
134
189
  end
135
190
 
136
- def initialize
137
191
 
138
- end
139
192
  end
@@ -1,4 +1,4 @@
1
1
 
2
2
  module ConsoleLauncher
3
- VERSION = '0.0.8'
3
+ VERSION = '0.0.9'
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: console-launcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juergen Hoffmann
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-05-25 00:00:00.000000000 Z
13
+ date: 2013-05-27 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rest-client