cloudflock-qt 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/qtflock +9 -0
- data/lib/cloudflock-qt.rb +13 -0
- data/lib/cloudflock-qt/app.rb +214 -0
- data/lib/cloudflock-qt/error.rb +19 -0
- data/lib/cloudflock-qt/results.rb +73 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 40697a3970659343568a5908dba4f69e9fbd8478
|
4
|
+
data.tar.gz: bb34bf94706b9419f410d4fdc27b17b0a39a31f6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a5e82a619a4e95fe5c8b695217ef5a3d3fd7d810839ae39645fbb3e1d616533db494f55d7f88ad6a77b4887797427f2ee0f903db02507e2cffe8fbc620783c46
|
7
|
+
data.tar.gz: a647877f2cc388b44d7c32037729479c01a1aa514e467818d173462a9268c2f72fddaa5148de89cc324cc4854e7d1059b8363d7bc5b18c3b1ffccc4839c3d54e
|
data/bin/qtflock
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Required to work around bug in Windows binary gem.
|
2
|
+
# Issue: https://github.com/ryanmelt/qtbindings/issues/69
|
3
|
+
require 'thread'
|
4
|
+
require 'Qt'
|
5
|
+
require 'cloudflock/app'
|
6
|
+
require 'cloudflock/task/server-profile'
|
7
|
+
|
8
|
+
# Public: Namespace for any application built around the CloudFlock API with a
|
9
|
+
# Qt interface.
|
10
|
+
module CloudFlockQt
|
11
|
+
# Public: Version number of the current gem.
|
12
|
+
VERSION = '0.7.2'
|
13
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require 'cloudflock-qt'
|
2
|
+
require 'cloudflock-qt/error'
|
3
|
+
require 'cloudflock-qt/results'
|
4
|
+
|
5
|
+
module CloudFlockQt
|
6
|
+
# Public: Class to be used for the main window.
|
7
|
+
class App < Qt::MainWindow
|
8
|
+
include CloudFlock::App::Common
|
9
|
+
include CloudFlock::Remote
|
10
|
+
# Public: Width of the main form window in pixels.
|
11
|
+
WINDOW_WIDTH = 300
|
12
|
+
# Public: Height of the main form window in pixels.
|
13
|
+
WINDOW_HEIGHT = 220
|
14
|
+
# Public: Title of the main form window.
|
15
|
+
WINDOW_TITLE = "QtFlock Profile #{CloudFlockQt::VERSION}"
|
16
|
+
|
17
|
+
# Public: Height of each row in the form in pixels
|
18
|
+
FORM_LINE_HEIGHT = 30
|
19
|
+
|
20
|
+
# Public: Raised when information provided to log in to a host is
|
21
|
+
# incomplete.
|
22
|
+
class HostNotConfigured < StandardError; end
|
23
|
+
|
24
|
+
# Public: Set up application state and create the main application window,
|
25
|
+
# populating it with the form to take target host details.
|
26
|
+
def initialize
|
27
|
+
super
|
28
|
+
|
29
|
+
init_instance_variables
|
30
|
+
init_ui
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# Internal: Set the default values for instance variables.
|
36
|
+
#
|
37
|
+
# Returns nothing.
|
38
|
+
def init_instance_variables
|
39
|
+
@hostname = ''
|
40
|
+
@username = 'root'
|
41
|
+
@password = ''
|
42
|
+
@root_password = ''
|
43
|
+
@port = '22'
|
44
|
+
@sudo = false
|
45
|
+
|
46
|
+
@lines = 0
|
47
|
+
end
|
48
|
+
|
49
|
+
# Internal: Set up the main window and add the form UI for target host
|
50
|
+
# definition.
|
51
|
+
#
|
52
|
+
# Returns nothing.
|
53
|
+
def init_ui
|
54
|
+
set_window_title WINDOW_TITLE
|
55
|
+
resize WINDOW_WIDTH, WINDOW_HEIGHT
|
56
|
+
|
57
|
+
file = menu_bar.add_menu('&File')
|
58
|
+
add_menu_item('E&xit', file, :quit)
|
59
|
+
|
60
|
+
build_main_form
|
61
|
+
|
62
|
+
show
|
63
|
+
end
|
64
|
+
|
65
|
+
# Internal: Build the form to collect data on the host to profile.
|
66
|
+
#
|
67
|
+
# Returns nothing.
|
68
|
+
def build_main_form
|
69
|
+
add_form_line_text('Hostname: ', :@hostname)
|
70
|
+
add_form_line_text('Username: ', :@username)
|
71
|
+
add_form_pass_text('Password: ', :@password)
|
72
|
+
add_form_pass_text('Root Password: ', :@root_password)
|
73
|
+
add_form_line_text('Port: ', :@port)
|
74
|
+
|
75
|
+
add_form_line_toggle('Use Sudo', :@sudo)
|
76
|
+
add_submit_button('Run Profile') { run_profile }
|
77
|
+
end
|
78
|
+
|
79
|
+
# Internal: Add an entry to a menu (e.g. 'File'), and assign an action to
|
80
|
+
# it.
|
81
|
+
#
|
82
|
+
# item_text - String containing the text to be displayed. An '&' character
|
83
|
+
# preceding a character will cause that character to be a
|
84
|
+
# hotkey for the item.
|
85
|
+
# menu - Qt::Menu to contain the new entry.
|
86
|
+
# action - Action to be taken upon triggering the menu item.
|
87
|
+
#
|
88
|
+
# Returns nothing.
|
89
|
+
def add_menu_item(item_text, menu, action)
|
90
|
+
item = Qt::Action.new item_text, self
|
91
|
+
menu.add_action item
|
92
|
+
connect(item, SIGNAL(:triggered), Qt::Application.instance, SLOT(action))
|
93
|
+
end
|
94
|
+
|
95
|
+
# Internal: Create a text input field and corrsponding label.
|
96
|
+
#
|
97
|
+
# item_text - String with which to populate a text label.
|
98
|
+
# varname - Symbol containing the name of the instance variable with
|
99
|
+
# which to associate the form entry.
|
100
|
+
#
|
101
|
+
# Returns the Qt::LineEdit object.
|
102
|
+
def add_form_line_text(item_text, varname)
|
103
|
+
@lines += 1
|
104
|
+
|
105
|
+
label = Qt::Label.new self
|
106
|
+
label.set_text item_text
|
107
|
+
label.adjust_size
|
108
|
+
label.move(5, FORM_LINE_HEIGHT * @lines)
|
109
|
+
|
110
|
+
input = Qt::LineEdit.new self
|
111
|
+
input.set_geometry 105, FORM_LINE_HEIGHT * @lines - 10, 190, FORM_LINE_HEIGHT
|
112
|
+
input.connect(SIGNAL('textChanged(QString)')) do |string|
|
113
|
+
instance_variable_set(varname, string)
|
114
|
+
end
|
115
|
+
input.set_text instance_variable_get(varname)
|
116
|
+
|
117
|
+
input
|
118
|
+
end
|
119
|
+
|
120
|
+
# Internal: Wrap add_form_line_text, ensuring the the text display mode is
|
121
|
+
# appropriate for passwords.
|
122
|
+
#
|
123
|
+
# item_text - String with which to populate a text label.
|
124
|
+
# varname - Symbol containing the name of the instance variable with
|
125
|
+
# which to associate the form entry.
|
126
|
+
#
|
127
|
+
# Returns nothing.
|
128
|
+
def add_form_pass_text(item_text, varname)
|
129
|
+
add_form_line_text(item_text, varname).echoMode = Qt::LineEdit::Password
|
130
|
+
end
|
131
|
+
|
132
|
+
# Internal: Create a toggle button input field.
|
133
|
+
#
|
134
|
+
# item_text - String which will be displayed on the toggle button.
|
135
|
+
# varname - Symbol containing the name of the instance variable with
|
136
|
+
# which to associate the form entry.
|
137
|
+
# block - Optional block to attach to clicking the toggle.
|
138
|
+
#
|
139
|
+
# Returns nothing.
|
140
|
+
def add_form_line_toggle(item_text, varname, &block)
|
141
|
+
@lines += 1
|
142
|
+
|
143
|
+
toggle = Qt::PushButton.new item_text, self
|
144
|
+
toggle.set_checkable true
|
145
|
+
toggle.set_geometry 5, FORM_LINE_HEIGHT * @lines - 5, 80, 30
|
146
|
+
if block.nil?
|
147
|
+
toggle.connect(SIGNAL(:clicked)) do
|
148
|
+
instance_variable_set(varname, toggle.is_checked)
|
149
|
+
end
|
150
|
+
else
|
151
|
+
toggle.connect(SIGNAL(:clicked), &block)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Internal: Create a submit button.
|
156
|
+
#
|
157
|
+
# item_text - String which will be displayed on the toggle button.
|
158
|
+
# varname - Symbol containing the name of the instance variable with
|
159
|
+
# which to associate the form entry.
|
160
|
+
# block - Optional block to attach to clicking the toggle.
|
161
|
+
#
|
162
|
+
# Returns nothing.
|
163
|
+
def add_submit_button(item_text, &block)
|
164
|
+
submit = Qt::PushButton.new item_text, self
|
165
|
+
submit.set_geometry 175, FORM_LINE_HEIGHT * @lines - 5, 120, 30
|
166
|
+
submit.connect(SIGNAL(:clicked), &block)
|
167
|
+
end
|
168
|
+
|
169
|
+
# Internal: Check that all necessary data is present, alerting the user if
|
170
|
+
# not. If everything appears present, attempt to profile the host.
|
171
|
+
#
|
172
|
+
# Returns nothing.
|
173
|
+
def run_profile
|
174
|
+
source_host = { hostname: @hostname, username: @username, port: @port,
|
175
|
+
password: @password, sudo: @sudo, ssh_key: '' }
|
176
|
+
check_source(source_host)
|
177
|
+
|
178
|
+
source_ssh = SSH.new(source_host)
|
179
|
+
profile = CloudFlock::Task::ServerProfile.new(source_ssh)
|
180
|
+
|
181
|
+
CloudFlockQt::ResultsWindow.new(profile)
|
182
|
+
rescue HostNotConfigured => e
|
183
|
+
CloudFlockQt::ErrorWindow.new(e.message)
|
184
|
+
rescue CloudFlock::Remote::SSH::InvalidHostname
|
185
|
+
CloudFlockQt::ErrorWindow.new("Unable to resolve '#{@hostname}'")
|
186
|
+
rescue Net::SSH::AuthenticationFailed
|
187
|
+
CloudFlockQt::ErrorWindow.new("Unable to log in as '#{@username}'")
|
188
|
+
rescue CloudFlock::Remote::SSH::SSHCannotConnect
|
189
|
+
CloudFlockQt::ErrorWindow.new("Cannot connect to #{@hostname}:#{@port}")
|
190
|
+
end
|
191
|
+
|
192
|
+
# Internal: Verify that all entries necessary for logging in to a remote
|
193
|
+
# host are present.
|
194
|
+
#
|
195
|
+
# Raises HostNotConfigured if any necessary information is not present.
|
196
|
+
#
|
197
|
+
# Returns nothing.
|
198
|
+
def check_source(host)
|
199
|
+
[:hostname, :username, :port].each do |option|
|
200
|
+
if host[option].to_s.empty?
|
201
|
+
raise(HostNotConfigured, "Missing #{option.to_s.capitalize}")
|
202
|
+
end
|
203
|
+
end
|
204
|
+
host[:sudo] = false if host[:username] == 'root'
|
205
|
+
|
206
|
+
# If non-root and using su, the root password is needed
|
207
|
+
if host[:username] == 'root' || host[:sudo]
|
208
|
+
host[:root_password] = host[:password]
|
209
|
+
else
|
210
|
+
raise HostNotConfigured if host[:root_password].to_s.empty?
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'cloudflock-qt'
|
2
|
+
|
3
|
+
module CloudFlockQt
|
4
|
+
# Public: Class to be used for error notifications.
|
5
|
+
class ErrorWindow < Qt::ErrorMessage
|
6
|
+
# Public: Width of the results window in pixels.
|
7
|
+
WINDOW_WIDTH = 300
|
8
|
+
# Public: Height of the results window in pixels.
|
9
|
+
WINDOW_HEIGHT = 150
|
10
|
+
|
11
|
+
# Public: Create and populate the window with results from profiling a
|
12
|
+
# remote host.
|
13
|
+
def initialize(message)
|
14
|
+
super()
|
15
|
+
|
16
|
+
show_message(message)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'cloudflock-qt'
|
2
|
+
|
3
|
+
module CloudFlockQt
|
4
|
+
# Public: Class to be used for results windows.
|
5
|
+
class ResultsWindow < Qt::Widget
|
6
|
+
# Public: Width of the results window in pixels.
|
7
|
+
WINDOW_WIDTH = 400
|
8
|
+
# Public: Height of the results window in pixels.
|
9
|
+
WINDOW_HEIGHT = 500
|
10
|
+
|
11
|
+
# Public: Create and populate the window with results from profiling a
|
12
|
+
# remote host.
|
13
|
+
def initialize(profile)
|
14
|
+
super()
|
15
|
+
|
16
|
+
init_ui(profile)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Internal: Create the results window and text field, then populate it with
|
22
|
+
# the results of a host profile.
|
23
|
+
#
|
24
|
+
# profile - CloudFlock::Task::ServerProfile object.
|
25
|
+
#
|
26
|
+
# Returns nothing.
|
27
|
+
def init_ui(profile)
|
28
|
+
hostname = profile.select_entries(/System/, /Hostname/).first.to_s
|
29
|
+
|
30
|
+
set_window_title "Results for #{hostname}"
|
31
|
+
resize WINDOW_WIDTH, WINDOW_HEIGHT
|
32
|
+
|
33
|
+
results = Qt::TextEdit.new self
|
34
|
+
results.set_geometry 5, 5, WINDOW_WIDTH - 5, WINDOW_HEIGHT - 5
|
35
|
+
results.set_text generate_report(profile)
|
36
|
+
|
37
|
+
show
|
38
|
+
end
|
39
|
+
|
40
|
+
# Internal: Generate a String representation of the profile run against a
|
41
|
+
# remote host.
|
42
|
+
#
|
43
|
+
# profile - CloudFlock::Task::ServerProfile object.
|
44
|
+
#
|
45
|
+
# Returns a String.
|
46
|
+
def host_info(profile)
|
47
|
+
data = profile.map { |section| [section.title, distill_entries(section)] }
|
48
|
+
data.map { |section| section.join("\n") }.join("\n\n")
|
49
|
+
end
|
50
|
+
|
51
|
+
# Internal: Filter any empty entries from a section, then map the rest to
|
52
|
+
# Strings.
|
53
|
+
#
|
54
|
+
# section - CloudFlock::Task::ServerProfile::Section
|
55
|
+
#
|
56
|
+
# Returns an Array containing Strings.
|
57
|
+
def distill_entries(section)
|
58
|
+
non_empty = section.entries.reject { |entry| entry.values.to_s.empty? }
|
59
|
+
non_empty.map { |entry| "#{entry.name}: #{entry.values}" }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Internal: Produce a human-readable report from the results of profiling a
|
63
|
+
# target host.
|
64
|
+
#
|
65
|
+
# profile - CloudFlock::Task::ServerProfile object.
|
66
|
+
#
|
67
|
+
# Returns a String.
|
68
|
+
def generate_report(profile)
|
69
|
+
profile_hash = profile.to_hash
|
70
|
+
host_info(profile_hash[:info])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cloudflock-qt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.7.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chris Wuest
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cloudflock
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.7'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.7.2
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.7'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.7.2
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: qtbindings
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '4.8'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '4.8'
|
47
|
+
description: Graphical frontend for CloudFlock in Qt
|
48
|
+
email: chris@chriswuest.com
|
49
|
+
executables:
|
50
|
+
- qtflock
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- bin/qtflock
|
55
|
+
- lib/cloudflock-qt.rb
|
56
|
+
- lib/cloudflock-qt/app.rb
|
57
|
+
- lib/cloudflock-qt/error.rb
|
58
|
+
- lib/cloudflock-qt/results.rb
|
59
|
+
homepage: http://github.com/cwuest/cloudflock-qt
|
60
|
+
licenses:
|
61
|
+
- Apache 2.0
|
62
|
+
metadata: {}
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubyforge_project:
|
79
|
+
rubygems_version: 2.2.2
|
80
|
+
signing_key:
|
81
|
+
specification_version: 4
|
82
|
+
summary: Unix migration automation
|
83
|
+
test_files: []
|