cloudflock 0.4.0

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.
Files changed (33) hide show
  1. data/bin/flock +32 -0
  2. data/bin/flock-profile +17 -0
  3. data/bin/flock-servers +24 -0
  4. data/bin/flock.default +24 -0
  5. data/lib/cloudflock/error.rb +26 -0
  6. data/lib/cloudflock/interface/cli/app/common/servers.rb +128 -0
  7. data/lib/cloudflock/interface/cli/app/servers/migrate.rb +357 -0
  8. data/lib/cloudflock/interface/cli/app/servers/profile.rb +88 -0
  9. data/lib/cloudflock/interface/cli/app/servers.rb +2 -0
  10. data/lib/cloudflock/interface/cli/console.rb +213 -0
  11. data/lib/cloudflock/interface/cli/opts/servers.rb +20 -0
  12. data/lib/cloudflock/interface/cli/opts.rb +87 -0
  13. data/lib/cloudflock/interface/cli.rb +15 -0
  14. data/lib/cloudflock/patch/fog.rb +113 -0
  15. data/lib/cloudflock/remote/ssh.rb +311 -0
  16. data/lib/cloudflock/target/servers/data/exceptions/base.txt +44 -0
  17. data/lib/cloudflock/target/servers/data/exceptions/platform/amazon.txt +10 -0
  18. data/lib/cloudflock/target/servers/data/exceptions/platform/debian.txt +0 -0
  19. data/lib/cloudflock/target/servers/data/exceptions/platform/redhat.txt +5 -0
  20. data/lib/cloudflock/target/servers/data/exceptions/platform/suse.txt +1 -0
  21. data/lib/cloudflock/target/servers/data/post-migration/chroot/base.txt +1 -0
  22. data/lib/cloudflock/target/servers/data/post-migration/chroot/platform/amazon.txt +19 -0
  23. data/lib/cloudflock/target/servers/data/post-migration/pre/base.txt +3 -0
  24. data/lib/cloudflock/target/servers/data/post-migration/pre/platform/amazon.txt +4 -0
  25. data/lib/cloudflock/target/servers/migrate.rb +466 -0
  26. data/lib/cloudflock/target/servers/platform/v1.rb +97 -0
  27. data/lib/cloudflock/target/servers/platform/v2.rb +93 -0
  28. data/lib/cloudflock/target/servers/platform.rb +133 -0
  29. data/lib/cloudflock/target/servers/profile.rb +394 -0
  30. data/lib/cloudflock/target/servers.rb +5 -0
  31. data/lib/cloudflock/version.rb +3 -0
  32. data/lib/cloudflock.rb +10 -0
  33. metadata +128 -0
@@ -0,0 +1,133 @@
1
+ require 'cpe'
2
+ require 'cloudflock'
3
+
4
+ # Public: Serves as a small class to easily map host specifications to Image
5
+ # and Flavor IDs in Rackspace Cloud.
6
+ #
7
+ # Examples
8
+ #
9
+ # # Build platform data for a given CPE object
10
+ # platform = Platform.new(cpe)
11
+ # platform.image_id
12
+ # # => Fixnum
13
+ class CloudFlock::Target::Servers::Platform
14
+ # Public: Gets/sets whether the target platform will be managed.
15
+ attr_accessor :managed
16
+ # Public: Gets/sets whether the target platform will use Rack Connect.
17
+ attr_accessor :rack_connect
18
+
19
+ # Public: Initialize the Platform object.
20
+ #
21
+ # cpe - CPE object from which to generate platform object.
22
+ #
23
+ # Raises ArgumentError if anything but a CPE object was given.
24
+ # Raises KeyError if the CPE object doesn't have a vendor or version defined.
25
+ def initialize(cpe)
26
+ raise ArgumentError unless cpe.kind_of?(CPE)
27
+ raise KeyError if cpe.vendor.nil? or cpe.version.nil?
28
+
29
+ @cpe = cpe
30
+ @distro = cpe.vendor
31
+ @product = cpe.product
32
+ @version = cpe.version
33
+ @managed = false
34
+ @rack_connect = false
35
+
36
+ build_maps
37
+ end
38
+
39
+ # Public: Generate a String of the platform's name/version suitable for
40
+ # display
41
+ #
42
+ # Returns a String describing the Platform
43
+ def to_s
44
+ "#{@distro.capitalize} #{@product.gsub(/_/, ' ').capitalize} #{@version}"
45
+ end
46
+
47
+ # Public: Return the Image ID to be used based on whether the account is
48
+ # managed, and the platform used
49
+ #
50
+ # Returns the Image ID corresponding to the Platform object as a String
51
+ def image
52
+ [:MANAGED_MAP, :UNMANAGED_MAP].each do |map|
53
+ unless self.class.const_defined?(map)
54
+ raise MapUndefined, "Const #{map} is undefined; maps appear unbuilt"
55
+ end
56
+ end
57
+
58
+ map = @managed ? self.class::MANAGED_MAP : self.class::UNMANAGED_MAP
59
+ distro = @distro.downcase.to_sym
60
+
61
+ unless map[distro].nil?
62
+ return map[distro][@version] unless map[distro][@version].nil?
63
+ return map[distro]["*"] unless map[distro]["*"].nil?
64
+ end
65
+
66
+ nil
67
+ end
68
+
69
+ # Public: Iterate through TARGET_LIST until a suitably large flavor_id is
70
+ # found, then return the appropriate index. If no entry can be found, raise
71
+ # ValueError.
72
+ #
73
+ # symbol - A Symbol referencing the search target in TARGET_LIST.
74
+ # value - A Fixnum containing the amount of memory or disk space required.
75
+ #
76
+ # Returns a Fixnum referencing the TARGET_LIST index.
77
+ # Raises ValueError if no symbol describes an appropriate target.
78
+ def get_target_by_symbol(symbol, value)
79
+ unless self.class.const_defined?(:FLAVOR_LIST)
80
+ raise MapUndefined, "FLAVOR_LIST is undefined; maps appear unbuild."
81
+ end
82
+
83
+ self.class::FLAVOR_LIST.each_with_index do |target, idx|
84
+ if target[symbol] > value
85
+ return idx
86
+ end
87
+ end
88
+
89
+ raise ValueError, "Unable to find a flavor matching #{symbol} #{value}"
90
+ end
91
+
92
+ # Internal: Build image and flavor maps
93
+ #
94
+ # Returns nothing
95
+ def build_maps
96
+ build_image_maps
97
+ build_flavor_maps
98
+ end
99
+
100
+ # Public: Give a recommendation for a Flavor ID and an Image ID which should
101
+ # suffice for a migration target host.
102
+ #
103
+ # args - Hash containing information on which to base the recommendation:
104
+ # :memory - Hash containing memory information:
105
+ # :total - Total amount of memory allocated to the host
106
+ # profiled.
107
+ # :mem_used - Amount of RAM in use at the time of
108
+ # profiling.
109
+ # :swapping? - Boolean denoting whether the host was
110
+ # swapping at the time of profiling.
111
+ # :disk - Fixnum containing the amount of disk which appears to be
112
+ # in use at the time of profiling.
113
+ #
114
+ # Returns a Hash containing the Flavor ID and a String containing the
115
+ # reasoning for the decision.
116
+ def build_recommendation(args)
117
+ recommendation = {}
118
+ target_mem = get_target_by_symbol(:mem, args[:memory][:mem_used])
119
+ target_mem += 1 if args[:memory][:swapping?]
120
+
121
+ target_disk = get_target_by_symbol(:hdd, args[:disk])
122
+
123
+ if target_mem >= target_disk
124
+ recommendation[:flavor] = target_mem
125
+ recommendation[:flavor_reason] = "RAM usage"
126
+ else
127
+ recommendation[:flavor] = target_disk
128
+ recommendation[:flavor_reason] = "Disk usage"
129
+ end
130
+
131
+ recommendation
132
+ end
133
+ end
@@ -0,0 +1,394 @@
1
+ require 'cloudflock/remote/ssh'
2
+ require 'cpe'
3
+
4
+ # Public: Provides methods to create a profile for a given host, mapping it to
5
+ # available public cloud offerings, and reference data gathered during this
6
+ # process.
7
+ #
8
+ # Examples
9
+ #
10
+ # # Generate a profile from a shell already logged in to a remote host
11
+ # profile = Profile.new(ssh_object)
12
+ # profile.build
13
+ #
14
+ # # Only determine the memory and I/O statistics for a host
15
+ # profile = Profile.new(ssh_object)
16
+ # profile.determine_memory
17
+ # profile.determine_io
18
+ class CloudFlock::Target::Servers::Profile
19
+ # Public: Array containing warnings generated by the info gathering process.
20
+ attr_reader :warnings
21
+
22
+ # Public: Initialize the Profile object.
23
+ #
24
+ # shell - An SSH object open to the host to be profiled.
25
+ #
26
+ # Raises ArgumentError if passed anything but an SSH object.
27
+ def initialize(shell)
28
+ raise ArgumentError unless shell.kind_of? CloudFlock::Remote::SSH
29
+
30
+ @shell = shell
31
+
32
+ @warnings = []
33
+ @info = {}
34
+ end
35
+
36
+ # Public: Run all available determinations against the SSH object.
37
+ #
38
+ # Returns nothing.
39
+ def build
40
+ determine_version
41
+ determine_arch
42
+ determine_hostname
43
+ determine_memory
44
+ determine_cpu
45
+ determine_disk
46
+ determine_ips
47
+ determine_io
48
+ determine_web
49
+ determine_db
50
+ determine_lib
51
+ determine_rsync
52
+ determine_processes
53
+ end
54
+
55
+ # Public: Determine vendor and version of the OS running on the target host,
56
+ # and create an appropriate CPE object for it, assigning it to @info[:cpe].
57
+ #
58
+ # Returns nothing.
59
+ def determine_version
60
+ release = @shell.query("CPE", "cat /etc/system-release-cpe")
61
+
62
+ begin
63
+ cpe = CPE.parse(release)
64
+ cpe.version.gsub!(/[^0-9.]/, '')
65
+ @info[:cpe] = cpe
66
+ return
67
+ rescue ArgumentError
68
+ cpe = CPE.new(part: CPE::OS, product: "linux")
69
+ end
70
+
71
+ issue = @shell.query("ISSUE", "cat /etc/issue")
72
+
73
+ case issue
74
+ when /Arch/
75
+ cpe.vendor = "Arch"
76
+ when /CentOS/
77
+ cpe.vendor = "CentOS"
78
+ issue.gsub!(/\.\d.*$/, '')
79
+ when /Debian/
80
+ cpe.vendor = "Debian"
81
+ issue.gsub!(/\.\d.*$/, '')
82
+ when /This is/
83
+ cpe.vendor = "Gentoo"
84
+ when /SUSE/
85
+ cpe.vendor = "openSUSE"
86
+ when /Ubuntu/
87
+ cpe.vendor = "Ubuntu"
88
+ when /Red/
89
+ cpe.vendor = "Redhat"
90
+ issue.gsub!(/\.\d.*$/, '')
91
+ else
92
+ cpe.vendor = "Unknown"
93
+ end
94
+
95
+ cpe.version = version_number(issue)
96
+
97
+ @info[:cpe] = cpe
98
+ end
99
+
100
+ # Public: Determine the architecture of the target host and assign it to
101
+ # @info[:arch].
102
+ #
103
+ # Returns nothing.
104
+ def determine_arch
105
+ uname = @shell.query("UNAME", "uname -m")
106
+ case uname
107
+ when /x86_64/
108
+ @info[:arch] = 'x86_64'
109
+ when /i\d86/
110
+ @info[:arch] = 'i386'
111
+ else
112
+ @info[:arch] = "Unknown"
113
+ end
114
+ end
115
+
116
+ # Public: Determine the hostname of the target host and assign it to
117
+ # @info[:hostname]
118
+ #
119
+ # Returns nothing.
120
+ def determine_hostname
121
+ @info[:hostname] = @shell.query("HOST", "hostname")
122
+ end
123
+
124
+ # Public: Determine the available and total memory on the target host as
125
+ # well as historical usage via sar(1), if possible. Assign these to
126
+ # @info[:memory] and @info[:memory_hist], respectively.
127
+ #
128
+ # Returns nothing.
129
+ def determine_memory
130
+ result = {}
131
+
132
+ free = %w{free -m |awk '$1 ~ /Mem/ {print $2, $2-$6-$7}; $1 ~ /Swap/
133
+ {print $3}'|xargs}.join(' ')
134
+ mem = @shell.query("MEMORY", free)
135
+ total, used, swap = mem.split(/\s+/)
136
+
137
+ result[:total] = total.to_i
138
+ result[:mem_used] = used.to_i
139
+ result[:swap_used] = swap.to_i
140
+ result[:swapping?] = swap.to_i > 0
141
+ @info[:memory] = result
142
+
143
+ # Determine average mem and swap usage
144
+ result = {}
145
+ sar_location = @shell.query("SAR", "which sar 2>/dev/null")
146
+ sar_command = %w{for l in $(find /var/log/ -name 'sa??'); do sar -r -f $l |
147
+ grep Average; done | awk '{I+=1; TOT=$2+$3; CACHE+=$5+$6;
148
+ FREE+=$2; SWAP+=$9;} END {CACHE=CACHE/I; FREE=FREE/I;
149
+ SWAP=SWAP/I; print (TOT-(CACHE+FREE))/TOT*100,
150
+ SWAP;}'}.join(' ')
151
+
152
+ if sar_location =~ /bin\//
153
+ sar_usage = @shell.query("HIST_MEM", sar_command)
154
+
155
+ if sar_usage =~ /\d \d/
156
+ hist_mem, hist_swap = sar_usage.split(/ /)
157
+ result[:mem_used] = hist_mem.to_i
158
+ result[:swap_used] = hist_swap.to_i
159
+ end
160
+ end
161
+
162
+ @info[:memory_hist] = result
163
+ end
164
+
165
+ # Public: Determine the number of CPUs present on the target host and the
166
+ # speed of the processors. Assign these to @info[:cpu][:count] and
167
+ # @info[:cpu][:speed] respectively.
168
+ #
169
+ # Returns nothing.
170
+ def determine_cpu
171
+ count_command = 'cat /proc/cpuinfo|grep "^processor\\s*: [0-9]"|wc -l'
172
+ speed_command = 'cat /proc/cpuinfo|grep "MHz"|head -1'
173
+ cpus = {}
174
+ cpus[:count] = @shell.query("CPU", count_command).to_i
175
+ cpus[:speed] = @shell.query("MHZ", speed_command).gsub(/.*: /, '').to_i
176
+ @info[:cpu] = cpus
177
+ end
178
+
179
+ # Public: Determine the amount of disk space in use on the target host and
180
+ # set that to @info[:disk].
181
+ #
182
+ # Returns nothing.
183
+ def determine_disk
184
+ # Use a less accurate (tends to inflate) method if du takes too long
185
+ df_command = "df 2>/dev/null |awk '$1 ~ /\\// {I = I + $3} END {print I}'"
186
+ disk = @shell.query("DISK_USED_DF", df_command)
187
+
188
+ # Result is returned as KiB used. We need GB used.
189
+ @info[:disk] = disk.to_f / 1000 ** 2
190
+ end
191
+
192
+ # Public: Determine the number of public and private IP addressess in use on
193
+ # the target host and assign that to @info[:ip].
194
+ #
195
+ # Returns nothing.
196
+ def determine_ips
197
+ ips = {:private => [], :public => []}
198
+
199
+ ip_command = %w{/sbin/ifconfig | grep 'inet addr' | egrep -v ':127' | sed
200
+ -e 's/.*addr:\([0-9.]*\) .*/\1/'}.join(' ')
201
+ ifconfig = @shell.query("IP_CONFIG", ip_command)
202
+
203
+ ifconfig.each_line do |ip|
204
+ ip.strip!
205
+ ips[rfc1918?(ip)] << ip
206
+ end
207
+
208
+ @info[:ip] = ips
209
+ end
210
+
211
+ # Public: Determine amount of historical I/O usage via sysstat and set it to
212
+ # @info[:io].
213
+ #
214
+ # Returns nothing.
215
+ def determine_io
216
+ io = {}
217
+
218
+ iostat = @shell.query("IOSTAT", "iostat -c | sed -n 4p | awk '{print $4}'")
219
+ io[:wait] = iostat.to_f
220
+
221
+ up = @shell.query("UPTIME", "uptime | sed -e 's/.*up\\([^,]*\\),.*/\\1/'")
222
+ io[:uptime] = up.chomp
223
+
224
+ @info[:io] = io
225
+ end
226
+
227
+ # Public: Determine the web server used on the host, and attempt to enumerate
228
+ # domain names configured on the server for both non-SSL and SSL; set this
229
+ # information to @info[:web]. Presently only Apache is supported.
230
+ #
231
+ # Returns nothing.
232
+ def determine_web
233
+ web = {}
234
+
235
+ netstat_command = %w{netstat -ntlp | awk '$4 ~ /:80$/ || $4 ~ /:443$/
236
+ {sub(/^[^\/]*\//, ""); print $NF}' | head -1}.join(' ')
237
+ web[:binary] = @shell.query("WEB_NETSTAT", netstat_command)
238
+
239
+ unless web[:binary].empty?
240
+ version_command = "`which #{web[:binary]}` -v | grep version"
241
+ web[:version] = @shell.query("WEB_VERSION", version_command)
242
+ web[:version].gsub!(/.*version: /i, '')
243
+ binary = web[:binary] == "httpd" ? "apachectl" : "apache2ctl"
244
+ binary << " -S 2>&1"
245
+
246
+ web_command = "#{binary} | grep ')' | grep -vi 'default' | wc -l"
247
+ hosts = @shell.query("WEB_HTTP", web_command)
248
+ web[:hosts_http] = hosts.to_i
249
+
250
+ ssl_command = "#{binary} | grep ':443'|grep -vi 'default' | wc -l"
251
+ ssl_hosts = @shell.query("WEB_HTTPS", ssl_command)
252
+ web[:hosts_https] = ssl_hosts.to_i
253
+ end
254
+
255
+ @info[:web] = web
256
+ end
257
+
258
+ # Public: Determine the amount of disk usage attributable to databases, as
259
+ # well as database count, and set this to @info[:database]. Currently
260
+ # supports MySQL.
261
+ #
262
+ # Returns nothing.
263
+ def determine_db
264
+ db = {}
265
+ mysql_count = %w{find /var/lib/mysql/* -maxdepth 0 -type d 2>/dev/null |
266
+ wc -l}.join(' ')
267
+ db[:count] = @shell.query("DB_MYSQL_COUNT", mysql_count)
268
+
269
+ mysql_size = "du -s /var/lib/mysql 2>/dev/null | awk '{print $1}'"
270
+ db[:size] = @shell.query("DB_MYSQL_SIZE", mysql_size)
271
+
272
+ db[:count] = db[:count].to_i
273
+ db[:size] = db[:size].to_i
274
+
275
+ @info[:db] = db
276
+ end
277
+
278
+ # Public: Gather information about the currently installed libc, ruby, perl,
279
+ # python and php versions on the host, then set these values to @info[:lib].
280
+ #
281
+ # Returns nothing.
282
+ def determine_lib
283
+ lib = {}
284
+
285
+ libc_command = %w{ls -al `find /lib /usr/lib -name 'libc.so*' | head -1` |
286
+ sed 's/.*-> //'}.join(' ')
287
+ lib[:libc] = @shell.query("LIBC", libc_command)
288
+ lib[:libc].gsub!(/^.*-|\.so$/, '')
289
+
290
+ lib[:perl] = @shell.query("PERL", "perl -e 'print $^V;'")
291
+ lib[:perl] = lib[:perl].gsub(/^v([0-9.]*).*/, '\1')
292
+
293
+ python_command = "python -c 'import sys; print sys.version' 2>/dev/null"
294
+ lib[:python] = @shell.query("PYTHON", python_command)
295
+ lib[:python] = lib[:python].gsub(/^([0-9.]*).*/m, '\1')
296
+
297
+ ruby_command = "ruby -e 'print RUBY_VERSION' 2>/dev/null"
298
+ lib[:ruby] = @shell.query("RUBY", ruby_command)
299
+
300
+ lib[:php] = @shell.query("PHP_VER", "php -v 2>/dev/null | head -1")
301
+ lib[:php] = lib[:php].gsub(/^PHP ([0-9.]*).*/, '\1')
302
+
303
+ @info[:lib] = lib
304
+ end
305
+
306
+ # Public: Check for the existence of rsync(1) on the host. Set @info[:rsync]
307
+ # accordingly.
308
+ #
309
+ # Returns nothing.
310
+ def determine_rsync
311
+ rsync_command = %w{which rsync 2>/dev/null || ([ -f
312
+ /root/.rackspace/rsync ] && printf
313
+ '/root/.rackspace/rsync') || printf
314
+ 'NONE'}.join(' ')
315
+
316
+ rsync = @shell.query("RSYNC", rsync_command)
317
+
318
+ @info[:rsync] = (rsync =~ /NONE/).nil? ? rsync : false
319
+ end
320
+
321
+ # Public: Check the process listing and store it in
322
+ #
323
+ # Returns nothing.
324
+ def determine_processes
325
+ ps_command = 'ps aux'
326
+
327
+ processes = @shell.query("PS_LIST", ps_command)
328
+ @info[:processes] = processes.gsub(/\r/, '').split(/\n/)
329
+
330
+ unless @info[:processes].grep(/psa/i).empty?
331
+ @warnings << "Server likely to be running Plesk"
332
+ end
333
+ unless @info[:processes].grep(/cpanellogd/i).empty?
334
+ @warnings << "Server likely to be running cPanel"
335
+ end
336
+ end
337
+
338
+ # Public: Simplify access to @info.
339
+ #
340
+ # key - Key to check in @info.
341
+ #
342
+ # Return value contained in @info by key.
343
+ def [](key)
344
+ @info[key]
345
+ end
346
+
347
+ # Public: Allow access to the list of keys extant in @info.
348
+ #
349
+ # Return an Array of keys present in @info.
350
+ def keys
351
+ @info.keys
352
+ end
353
+
354
+ # Public: Return server information and warnings as a Hash. Useful for
355
+ # calling Hash#merge.
356
+ #
357
+ # Return info Hash.
358
+ def to_hash
359
+ @info.merge({warnings: @warnings})
360
+ end
361
+
362
+ # Internal: Deconstruct the version String provided in order to strip out
363
+ # extraneous data before and after the version number. Version number
364
+ # strings are defined as beginning with a digit, ending with a digit, and
365
+ # containing nothing but digits and at most one decimal point.
366
+ #
367
+ # version - A String containing version number of the OS on the target host.
368
+ #
369
+ # Returns a String containing the parsed version string.
370
+ def version_number(version)
371
+ if version =~ /\d/
372
+ version.gsub(/^[^\d]*/, '').gsub(/[^\d]*$/, '').gsub(/(\d*\.\d*).*/, '\1')
373
+ else
374
+ "-"
375
+ end
376
+ end
377
+
378
+ # Internal: Determine whether a given IP resides in a block designated as
379
+ # private by RFC1918.
380
+ #
381
+ # ip - A String containing an IP address.
382
+ #
383
+ # Returns :private or :public Symbol based on whether the IP is private.
384
+ def rfc1918?(ip)
385
+ octets = ip.split /\./
386
+ if octets[0] == "10" || (octets[0] == "192" && octets[1] == "168")
387
+ return :private
388
+ elsif octets[0] == "172" && octets[1].to_i >=16 && octets[1].to_i <= 31
389
+ return :private
390
+ end
391
+
392
+ :public
393
+ end
394
+ end
@@ -0,0 +1,5 @@
1
+ require 'cloudflock'
2
+ require 'cloudflock/target/servers/profile'
3
+ require 'cloudflock/target/servers/migrate'
4
+ require 'cloudflock/target/servers/platform/v1'
5
+ require 'cloudflock/target/servers/platform/v2'
@@ -0,0 +1,3 @@
1
+ module CloudFlock
2
+ VERSION = '0.4.0'
3
+ end
data/lib/cloudflock.rb ADDED
@@ -0,0 +1,10 @@
1
+ module CloudFlock
2
+ module Remote; end
3
+ module Interface; end
4
+ module Target;
5
+ module Servers; end
6
+ end
7
+ end
8
+
9
+ require 'cloudflock/version'
10
+ require 'cloudflock/error'
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cloudflock
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chris Wuest
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fog
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: expectr
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: cpe
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: CloudFlock is a library and toolchain focused on migration
63
+ email: chris@chriswuest.com
64
+ executables:
65
+ - flock
66
+ - flock-profile
67
+ - flock-servers
68
+ extensions: []
69
+ extra_rdoc_files: []
70
+ files:
71
+ - lib/cloudflock.rb
72
+ - lib/cloudflock/error.rb
73
+ - lib/cloudflock/interface/cli.rb
74
+ - lib/cloudflock/interface/cli/app/common/servers.rb
75
+ - lib/cloudflock/interface/cli/app/servers.rb
76
+ - lib/cloudflock/interface/cli/app/servers/migrate.rb
77
+ - lib/cloudflock/interface/cli/app/servers/profile.rb
78
+ - lib/cloudflock/interface/cli/console.rb
79
+ - lib/cloudflock/interface/cli/opts.rb
80
+ - lib/cloudflock/interface/cli/opts/servers.rb
81
+ - lib/cloudflock/patch/fog.rb
82
+ - lib/cloudflock/remote/ssh.rb
83
+ - lib/cloudflock/target/servers.rb
84
+ - lib/cloudflock/target/servers/data/exceptions/base.txt
85
+ - lib/cloudflock/target/servers/data/exceptions/platform/amazon.txt
86
+ - lib/cloudflock/target/servers/data/exceptions/platform/debian.txt
87
+ - lib/cloudflock/target/servers/data/exceptions/platform/redhat.txt
88
+ - lib/cloudflock/target/servers/data/exceptions/platform/suse.txt
89
+ - lib/cloudflock/target/servers/data/post-migration/chroot/base.txt
90
+ - lib/cloudflock/target/servers/data/post-migration/chroot/platform/amazon.txt
91
+ - lib/cloudflock/target/servers/data/post-migration/pre/base.txt
92
+ - lib/cloudflock/target/servers/data/post-migration/pre/platform/amazon.txt
93
+ - lib/cloudflock/target/servers/migrate.rb
94
+ - lib/cloudflock/target/servers/platform.rb
95
+ - lib/cloudflock/target/servers/platform/v1.rb
96
+ - lib/cloudflock/target/servers/platform/v2.rb
97
+ - lib/cloudflock/target/servers/profile.rb
98
+ - lib/cloudflock/version.rb
99
+ - bin/flock
100
+ - bin/flock-profile
101
+ - bin/flock-servers
102
+ - bin/flock.default
103
+ homepage: http://github.com/cwuest/cloudflock
104
+ licenses:
105
+ - Apache 2.0
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ! '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ! '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubyforge_project:
124
+ rubygems_version: 1.8.25
125
+ signing_key:
126
+ specification_version: 3
127
+ summary: Server migration automation
128
+ test_files: []