cloudflock 0.6.1 → 0.7.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 (52) hide show
  1. checksums.yaml +15 -0
  2. data/bin/cloudflock +7 -1
  3. data/bin/cloudflock-files +2 -14
  4. data/bin/cloudflock-profile +3 -15
  5. data/bin/cloudflock-servers +3 -22
  6. data/bin/cloudflock.default +3 -22
  7. data/lib/cloudflock/app/common/cleanup/unix.rb +23 -0
  8. data/lib/cloudflock/app/common/cleanup.rb +107 -0
  9. data/lib/cloudflock/app/common/exclusions/unix/centos.rb +18 -0
  10. data/lib/cloudflock/app/common/exclusions/unix/redhat.rb +18 -0
  11. data/lib/cloudflock/app/common/exclusions/unix.rb +58 -0
  12. data/lib/cloudflock/app/common/exclusions.rb +57 -0
  13. data/lib/cloudflock/app/common/platform_action.rb +59 -0
  14. data/lib/cloudflock/app/common/rackspace.rb +63 -0
  15. data/lib/cloudflock/app/common/servers.rb +673 -0
  16. data/lib/cloudflock/app/files-migrate.rb +246 -0
  17. data/lib/cloudflock/app/server-migrate.rb +327 -0
  18. data/lib/cloudflock/app/server-profile.rb +130 -0
  19. data/lib/cloudflock/app.rb +87 -0
  20. data/lib/cloudflock/error.rb +6 -19
  21. data/lib/cloudflock/errstr.rb +31 -0
  22. data/lib/cloudflock/remote/files.rb +82 -22
  23. data/lib/cloudflock/remote/ssh.rb +234 -278
  24. data/lib/cloudflock/target/servers/platform.rb +92 -115
  25. data/lib/cloudflock/target/servers/profile.rb +331 -340
  26. data/lib/cloudflock/task/server-profile.rb +651 -0
  27. data/lib/cloudflock.rb +6 -8
  28. metadata +49 -68
  29. data/lib/cloudflock/interface/cli/app/common/servers.rb +0 -128
  30. data/lib/cloudflock/interface/cli/app/files.rb +0 -179
  31. data/lib/cloudflock/interface/cli/app/servers/migrate.rb +0 -491
  32. data/lib/cloudflock/interface/cli/app/servers/profile.rb +0 -88
  33. data/lib/cloudflock/interface/cli/app/servers.rb +0 -2
  34. data/lib/cloudflock/interface/cli/console.rb +0 -213
  35. data/lib/cloudflock/interface/cli/opts/servers.rb +0 -20
  36. data/lib/cloudflock/interface/cli/opts.rb +0 -87
  37. data/lib/cloudflock/interface/cli.rb +0 -15
  38. data/lib/cloudflock/target/servers/data/exceptions/base.txt +0 -44
  39. data/lib/cloudflock/target/servers/data/exceptions/platform/amazon.txt +0 -10
  40. data/lib/cloudflock/target/servers/data/exceptions/platform/centos.txt +0 -7
  41. data/lib/cloudflock/target/servers/data/exceptions/platform/debian.txt +0 -0
  42. data/lib/cloudflock/target/servers/data/exceptions/platform/redhat.txt +0 -7
  43. data/lib/cloudflock/target/servers/data/exceptions/platform/suse.txt +0 -1
  44. data/lib/cloudflock/target/servers/data/post-migration/chroot/base.txt +0 -1
  45. data/lib/cloudflock/target/servers/data/post-migration/chroot/platform/amazon.txt +0 -19
  46. data/lib/cloudflock/target/servers/data/post-migration/pre/base.txt +0 -3
  47. data/lib/cloudflock/target/servers/data/post-migration/pre/platform/amazon.txt +0 -4
  48. data/lib/cloudflock/target/servers/migrate.rb +0 -466
  49. data/lib/cloudflock/target/servers/platform/v1.rb +0 -97
  50. data/lib/cloudflock/target/servers/platform/v2.rb +0 -93
  51. data/lib/cloudflock/target/servers.rb +0 -5
  52. data/lib/cloudflock/version.rb +0 -3
metadata CHANGED
@@ -1,147 +1,128 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudflock
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
5
- prerelease:
4
+ version: 0.7.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Chris Wuest
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-07-25 00:00:00.000000000 Z
11
+ date: 2014-04-10 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: fog
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ~>
20
18
  - !ruby/object:Gem::Version
21
- version: 1.11.1
19
+ version: '1.21'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ~>
28
25
  - !ruby/object:Gem::Version
29
- version: 1.11.1
26
+ version: '1.21'
30
27
  - !ruby/object:Gem::Dependency
31
- name: multi_json
28
+ name: cpe
32
29
  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
30
  requirements:
43
- - - ! '>='
31
+ - - ~>
44
32
  - !ruby/object:Gem::Version
45
- version: '0'
46
- - !ruby/object:Gem::Dependency
47
- name: expectr
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
33
+ version: '0.5'
51
34
  - - ! '>='
52
35
  - !ruby/object:Gem::Version
53
- version: '0'
36
+ version: 0.5.0
54
37
  type: :runtime
55
38
  prerelease: false
56
39
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
40
  requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: '0.5'
59
44
  - - ! '>='
60
45
  - !ruby/object:Gem::Version
61
- version: '0'
46
+ version: 0.5.0
62
47
  - !ruby/object:Gem::Dependency
63
- name: cpe
48
+ name: console-glitter
64
49
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
50
  requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '0.1'
67
54
  - - ! '>='
68
55
  - !ruby/object:Gem::Version
69
- version: '0'
56
+ version: 0.1.4
70
57
  type: :runtime
71
58
  prerelease: false
72
59
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
60
  requirements:
61
+ - - ~>
62
+ - !ruby/object:Gem::Version
63
+ version: '0.1'
75
64
  - - ! '>='
76
65
  - !ruby/object:Gem::Version
77
- version: '0'
66
+ version: 0.1.4
78
67
  description: CloudFlock is a library and toolchain focused on migration
79
68
  email: chris@chriswuest.com
80
69
  executables:
81
70
  - cloudflock
71
+ - cloudflock-files
82
72
  - cloudflock-profile
83
73
  - cloudflock-servers
74
+ - cloudflock.default
84
75
  extensions: []
85
76
  extra_rdoc_files: []
86
77
  files:
78
+ - bin/cloudflock
79
+ - bin/cloudflock-files
80
+ - bin/cloudflock-profile
81
+ - bin/cloudflock-servers
82
+ - bin/cloudflock.default
87
83
  - lib/cloudflock.rb
84
+ - lib/cloudflock/app.rb
85
+ - lib/cloudflock/app/common/cleanup.rb
86
+ - lib/cloudflock/app/common/cleanup/unix.rb
87
+ - lib/cloudflock/app/common/exclusions.rb
88
+ - lib/cloudflock/app/common/exclusions/unix.rb
89
+ - lib/cloudflock/app/common/exclusions/unix/centos.rb
90
+ - lib/cloudflock/app/common/exclusions/unix/redhat.rb
91
+ - lib/cloudflock/app/common/platform_action.rb
92
+ - lib/cloudflock/app/common/rackspace.rb
93
+ - lib/cloudflock/app/common/servers.rb
94
+ - lib/cloudflock/app/files-migrate.rb
95
+ - lib/cloudflock/app/server-migrate.rb
96
+ - lib/cloudflock/app/server-profile.rb
88
97
  - lib/cloudflock/error.rb
89
- - lib/cloudflock/interface/cli.rb
90
- - lib/cloudflock/interface/cli/app/common/servers.rb
91
- - lib/cloudflock/interface/cli/app/files.rb
92
- - lib/cloudflock/interface/cli/app/servers.rb
93
- - lib/cloudflock/interface/cli/app/servers/migrate.rb
94
- - lib/cloudflock/interface/cli/app/servers/profile.rb
95
- - lib/cloudflock/interface/cli/console.rb
96
- - lib/cloudflock/interface/cli/opts.rb
97
- - lib/cloudflock/interface/cli/opts/servers.rb
98
+ - lib/cloudflock/errstr.rb
98
99
  - lib/cloudflock/remote/files.rb
99
100
  - lib/cloudflock/remote/ssh.rb
100
- - lib/cloudflock/target/servers.rb
101
- - lib/cloudflock/target/servers/data/exceptions/base.txt
102
- - lib/cloudflock/target/servers/data/exceptions/platform/amazon.txt
103
- - lib/cloudflock/target/servers/data/exceptions/platform/centos.txt
104
- - lib/cloudflock/target/servers/data/exceptions/platform/debian.txt
105
- - lib/cloudflock/target/servers/data/exceptions/platform/redhat.txt
106
- - lib/cloudflock/target/servers/data/exceptions/platform/suse.txt
107
- - lib/cloudflock/target/servers/data/post-migration/chroot/base.txt
108
- - lib/cloudflock/target/servers/data/post-migration/chroot/platform/amazon.txt
109
- - lib/cloudflock/target/servers/data/post-migration/pre/base.txt
110
- - lib/cloudflock/target/servers/data/post-migration/pre/platform/amazon.txt
111
- - lib/cloudflock/target/servers/migrate.rb
112
101
  - lib/cloudflock/target/servers/platform.rb
113
- - lib/cloudflock/target/servers/platform/v1.rb
114
- - lib/cloudflock/target/servers/platform/v2.rb
115
102
  - lib/cloudflock/target/servers/profile.rb
116
- - lib/cloudflock/version.rb
117
- - bin/cloudflock
118
- - bin/cloudflock-files
119
- - bin/cloudflock-profile
120
- - bin/cloudflock-servers
121
- - bin/cloudflock.default
103
+ - lib/cloudflock/task/server-profile.rb
122
104
  homepage: http://github.com/cwuest/cloudflock
123
105
  licenses:
124
106
  - Apache 2.0
107
+ metadata: {}
125
108
  post_install_message:
126
109
  rdoc_options: []
127
110
  require_paths:
128
111
  - lib
129
112
  required_ruby_version: !ruby/object:Gem::Requirement
130
- none: false
131
113
  requirements:
132
114
  - - ! '>='
133
115
  - !ruby/object:Gem::Version
134
116
  version: '0'
135
117
  required_rubygems_version: !ruby/object:Gem::Requirement
136
- none: false
137
118
  requirements:
138
119
  - - ! '>='
139
120
  - !ruby/object:Gem::Version
140
121
  version: '0'
141
122
  requirements: []
142
123
  rubyforge_project:
143
- rubygems_version: 1.8.25
124
+ rubygems_version: 2.2.2
144
125
  signing_key:
145
- specification_version: 3
146
- summary: Server migration automation
126
+ specification_version: 4
127
+ summary: Unix migration automation
147
128
  test_files: []
@@ -1,128 +0,0 @@
1
- require 'cloudflock'
2
- require 'cloudflock/interface/cli'
3
- require 'cloudflock/remote/ssh'
4
-
5
- # Public: The ServersCommon module provides common methods for CLI interaction
6
- # pertaining to interaction with remote (Unix) servers.
7
- module CloudFlock::Interface::CLI::App::Common::Servers
8
- include CloudFlock::Target::Servers
9
-
10
- SSH = CloudFlock::Remote::SSH
11
- CLI = CloudFlock::Interface::CLI::Console
12
-
13
- # Internal: Collect information about the source server to be migrated.
14
- #
15
- # opts - Hash containing any applicable options mappings for the server in
16
- # question.
17
- #
18
- # Returns a Hash containing information pertinent to logging in to a host.
19
- def define_source(opts)
20
- host = {}
21
-
22
- host[:host] = opts[:source_host] || CLI.prompt("Source host")
23
- host[:port] = opts[:source_port] || CLI.prompt("Source SSH port",
24
- default_answer: "22")
25
- host[:username] = opts[:source_user] || CLI.prompt("Source username",
26
- default_answer: "root")
27
- host[:password] = opts[:source_pass] || CLI.prompt("Source password",
28
- default_answer: "")
29
-
30
- until host[:public_key].kind_of?(String)
31
- key = opts[:public_key] || CLI.prompt("SSH Key", default_answer: "")
32
- if File.file?(File.expand_path(key)) || key.empty?
33
- host[:public_key] = key
34
- end
35
- end
36
-
37
- # Only need to use sudo if the user isn't root
38
- if host[:username] == "root"
39
- host[:sudo] = false
40
- elsif !opts[:source_sudo].nil?
41
- host[:sudo] = opts[:source_sudo]
42
- else
43
- host[:sudo] = CLI.prompt_yn("Use sudo? (Y/N)", default_answer: "Y")
44
- end
45
-
46
- # We need the root pass if non-root and no sudo
47
- if host[:username] == "root" || host[:sudo]
48
- host[:root_pass] = host[:password]
49
- else
50
- host[:root_pass] = CLI.prompt("Password for root")
51
- end
52
-
53
- host
54
- end
55
-
56
- # Internal: Collect information about the destination server to target in a
57
- # migration -- only used for resume functions.
58
- #
59
- # Returns a Hash containing information pertinent to logging in to a host.
60
- def define_destination
61
- host = Hash.new
62
-
63
- host[:host] = CLI.prompt("Destination host")
64
- host[:password] = CLI.prompt("Destination root password")
65
- host[:pre_steps] = CLI.prompt_yn("Perform pre-migration steps? (Y/N)")
66
- host[:username] = "root"
67
-
68
- host
69
- end
70
-
71
- # Internal: Initiate a connection to a given host and obtain root privileges.
72
- #
73
- # host - Hash containing information for connecting to the host:
74
- # :host - String containing the location to which to connect.
75
- # :port - String or Fixnum containing the port on which ssh
76
- # listens. (default: "22")
77
- # :username - String containing the username to use when logging in.
78
- # :password - String containing the password for the above user.
79
- # :sudo - Boolean value defining whether to use sudo to obtain
80
- # root. (default: false)
81
- # :root_pass - String containing the password to use to obtain root,
82
- # if the user isn't root and sudo isn't used.
83
- # :verbose - Boolean value defining whether to flush output to
84
- # STDOUT. (default: false)
85
- #
86
- # Returns an SSH object.
87
- # Raises ArgumentError unless at least host and user are defined.
88
- def host_login(host)
89
- if host[:host].nil? || host[:username].nil?
90
- raise ArgumentError, "Need at least host and username defined"
91
- end
92
-
93
- host[:flush_buffer] = host[:verbose] || false
94
-
95
- ssh = SSH.new(host)
96
- ssh.get_root(host[:root_pass], host[:sudo])
97
-
98
- ssh
99
- end
100
-
101
- # Internal: Initiate a connection to a destination host.
102
- #
103
- # host - Hash containing information for connecting to the host:
104
- # :host - String containing the location to which to connect.
105
- # :password - String containing the password for the above user.
106
- # :verbose - Boolean value defining whether to flush output to
107
- # STDOUT. (default: false)
108
- #
109
- # Returns an SSH object.
110
- # Raises ArgumentError unless at least host and user are defined.
111
- def destination_login(host)
112
- host[:username] = "root"
113
- message = "Connecting to destination host (password: #{host[:password]})"
114
- r = 0
115
-
116
- destination_host = CLI.spinner(message) do
117
- begin
118
- host_login(host)
119
- rescue Timeout::Error
120
- if (r += 1) < 5
121
- sleep 300
122
- retry
123
- end
124
- raise
125
- end
126
- end
127
- end
128
- end
@@ -1,179 +0,0 @@
1
- require 'cloudflock'
2
- require 'cloudflock/interface/cli'
3
- require 'cloudflock/remote/files'
4
- require 'tempfile'
5
- require 'thread'
6
- require 'fog'
7
-
8
- # Public: The Files app provides the interface to perform migrations of
9
- # File/Object storage (e.g. Amazon S3, Local files and Rackspace Cloud Files).
10
- class CloudFlock::Interface::CLI::App::Files
11
- CLI = CloudFlock::Interface::CLI::Console
12
-
13
- DOWNLOAD_THREAD_COUNT = 4
14
- UPLOAD_THREAD_COUNT = 4
15
-
16
- # Public: Begin Files migration on the command line
17
- #
18
- # opts - Hash containing options mappings.
19
- def initialize(opts)
20
- @options = opts
21
- @download_finished = false
22
- @download_mutex = Mutex.new
23
- @upload_mutex = Mutex.new
24
- @download_list = []
25
- @upload_list = []
26
-
27
- source_store = define_store("source")
28
- destination_store = define_store("destination")
29
-
30
- @source_container = define_container(source_store, "source")
31
- @destination_container = define_container(destination_store, "destination",
32
- true)
33
-
34
- if perform_migration
35
- puts "#{CLI.bold}#{CLI.blue}*** Migration complete#{CLI.reset}\a"
36
- else
37
- puts "#{CLI.bold}#{CLI.red}*** Migration failed#{CLI.reset}\a"
38
- end
39
- rescue Excon::Errors::Unauthorized => err
40
- puts "A provider has returned an Unauthorized error."
41
- puts err.inspect if @options[:verbose]
42
- exit 1
43
- end
44
-
45
- # Internal: Migrate objects from the source store to the destination store.
46
- #
47
- # Returns a boolean value corresponding to whether the migration has
48
- # completed successfully.
49
- def perform_migration
50
- download_threads = []
51
- upload_threads = []
52
-
53
- @source_container.files.each { |f| @download_list.push(f) }
54
-
55
- DOWNLOAD_THREAD_COUNT.times do
56
- download_threads << download_thread
57
- end
58
- UPLOAD_THREAD_COUNT.times do
59
- upload_threads << upload_thread
60
- end
61
-
62
- download_threads.each { |t| t.join }
63
- @download_finished = true
64
- upload_threads.each { |t| t.join }
65
- true
66
- rescue => e
67
- if @options[:verbose]
68
- puts "#{CLI.bold}#{CLI.red}*** Error ***#{CLI.reset}"
69
- puts e.inspect
70
- puts e.backtrace
71
- puts
72
- end
73
- false
74
- end
75
-
76
- # Internal: Create a new Thread to download objects from the source
77
- # container.
78
- #
79
- # Returns a Thread.
80
- def download_thread
81
- Thread.new do
82
- file = nil
83
- until @download_list.empty?
84
- @download_mutex.synchronize do
85
- file = @download_list.pop
86
- end
87
- next if file.nil?
88
- # AWS stores directories as their own object
89
- next if file.content_length == 0 && file.key =~ /\/$/
90
-
91
- tmp = Tempfile.new(file.object_id.to_s)
92
- @source_container.files.get(file.key) do |data, rem, cl|
93
- tmp.syswrite(data)
94
- end
95
- tmp.flush
96
- tmp.rewind
97
- @upload_mutex.synchronize do
98
- @upload_list.push(body: tmp, key: file.key)
99
- end
100
- end
101
- end
102
- end
103
-
104
- # Internal: Create a new Thread to upload objects to the desination
105
- # container.
106
- #
107
- # Returns a Thread.
108
- def upload_thread
109
- Thread.new do
110
- file = nil
111
- until @upload_list.empty? && @download_finished
112
- sleep 0.1
113
- @upload_mutex.synchronize do
114
- file = @upload_list.pop
115
- end
116
- next if file.nil?
117
- @destination_container.files.create(file)
118
- end
119
- end
120
- end
121
-
122
- # Internal: Ascertain the location for a data store.
123
- #
124
- # desc - String containing a description for the file store.
125
- #
126
- # Returns a Fog object pointing to the data store.
127
- # Raises ArgumentError if desc isn't a String.
128
- def define_store(desc)
129
- unless desc.kind_of?(String)
130
- raise ArgumentError, "String expected"
131
- end
132
- store = {}
133
- store[:provider] = CLI.prompt("#{desc} provider (aws, local, rax)",
134
- valid_answers: ["rax", "aws", "local"])
135
- case store[:provider]
136
- when 'rax'
137
- store[:provider] = 'Rackspace'
138
- store[:rackspace_username] = CLI.prompt("Rackspace username")
139
- store[:rackspace_api_key] = CLI.prompt("Rackspace API key")
140
- when 'aws'
141
- store[:provider] = 'AWS'
142
- store[:aws_access_key_id] = CLI.prompt("AWS Access Key ID")
143
- store[:aws_secret_access_key] = CLI.prompt("AWS secret access key")
144
- when 'local'
145
- store[:local_root] = CLI.prompt("#{desc} location")
146
- end
147
-
148
- CloudFlock::Remote::Files.connect(store)
149
- end
150
-
151
- # Internal: Obtain the name of a container.
152
- #
153
- # store - Fog object pointing to a Fog::Storage object.
154
- # desc - String containing a description for the container.
155
- # create - Boolean value indicating whether to create the container.
156
- #
157
- # Returns a Fog object pointing to the container.
158
- # Raises ArgumentError if store isn't a Fog::Storage object.
159
- # Raises ArgumentError if desc isn't a String.
160
- def define_container(store, desc, create=false)
161
- unless store.class.to_s =~ /^Fog::Storage/
162
- raise ArgumentError, "Fog Storage object expected"
163
- end
164
- unless desc.kind_of?(String)
165
- raise ArgumentError, "String expected"
166
- end
167
-
168
- if create
169
- container = CLI.prompt("#{desc} container name")
170
- return store.directories.create(key: container)
171
- else
172
- puts "Available containers:"
173
- puts store.directories.map(&:key)
174
- container = CLI.prompt("#{desc} container name",
175
- valid_answers: store.directories.map(&:key))
176
- return store.directories.select { |i| i.key == container }[0]
177
- end
178
- end
179
- end