cloudflock 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/flock +32 -0
- data/bin/flock-profile +17 -0
- data/bin/flock-servers +24 -0
- data/bin/flock.default +24 -0
- data/lib/cloudflock/error.rb +26 -0
- data/lib/cloudflock/interface/cli/app/common/servers.rb +128 -0
- data/lib/cloudflock/interface/cli/app/servers/migrate.rb +357 -0
- data/lib/cloudflock/interface/cli/app/servers/profile.rb +88 -0
- data/lib/cloudflock/interface/cli/app/servers.rb +2 -0
- data/lib/cloudflock/interface/cli/console.rb +213 -0
- data/lib/cloudflock/interface/cli/opts/servers.rb +20 -0
- data/lib/cloudflock/interface/cli/opts.rb +87 -0
- data/lib/cloudflock/interface/cli.rb +15 -0
- data/lib/cloudflock/patch/fog.rb +113 -0
- data/lib/cloudflock/remote/ssh.rb +311 -0
- data/lib/cloudflock/target/servers/data/exceptions/base.txt +44 -0
- data/lib/cloudflock/target/servers/data/exceptions/platform/amazon.txt +10 -0
- data/lib/cloudflock/target/servers/data/exceptions/platform/debian.txt +0 -0
- data/lib/cloudflock/target/servers/data/exceptions/platform/redhat.txt +5 -0
- data/lib/cloudflock/target/servers/data/exceptions/platform/suse.txt +1 -0
- data/lib/cloudflock/target/servers/data/post-migration/chroot/base.txt +1 -0
- data/lib/cloudflock/target/servers/data/post-migration/chroot/platform/amazon.txt +19 -0
- data/lib/cloudflock/target/servers/data/post-migration/pre/base.txt +3 -0
- data/lib/cloudflock/target/servers/data/post-migration/pre/platform/amazon.txt +4 -0
- data/lib/cloudflock/target/servers/migrate.rb +466 -0
- data/lib/cloudflock/target/servers/platform/v1.rb +97 -0
- data/lib/cloudflock/target/servers/platform/v2.rb +93 -0
- data/lib/cloudflock/target/servers/platform.rb +133 -0
- data/lib/cloudflock/target/servers/profile.rb +394 -0
- data/lib/cloudflock/target/servers.rb +5 -0
- data/lib/cloudflock/version.rb +3 -0
- data/lib/cloudflock.rb +10 -0
- metadata +128 -0
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'cloudflock/target/servers'
|
2
|
+
require 'cloudflock/interface/cli/app/common/servers'
|
3
|
+
|
4
|
+
# Public: The Profile class provides the interface to produces profiles
|
5
|
+
# describing servers running Unix-like operating systems.
|
6
|
+
class CloudFlock::Interface::CLI::App::Servers::Profile
|
7
|
+
include CloudFlock::Interface::CLI::App::Common::Servers
|
8
|
+
include CloudFlock::Target::Servers
|
9
|
+
CLI = CloudFlock::Interface::CLI::Console
|
10
|
+
|
11
|
+
# Public: Begin Servers migration on the command line
|
12
|
+
#
|
13
|
+
# opts - Hash containing options mappings.
|
14
|
+
def initialize(opts)
|
15
|
+
resume = opts[:resume]
|
16
|
+
source_host_def = define_source(opts[:config])
|
17
|
+
source_host_ssh = CLI.spinner("Logging in to #{source_host_def[:host]}") do
|
18
|
+
host_login(source_host_def)
|
19
|
+
end
|
20
|
+
|
21
|
+
profile = CLI.spinner("Checking source host") do
|
22
|
+
profile = Profile.new(source_host_ssh)
|
23
|
+
profile.build
|
24
|
+
profile
|
25
|
+
end
|
26
|
+
platform = Platform::V2.new(profile[:cpe])
|
27
|
+
|
28
|
+
memory = profile[:memory]
|
29
|
+
memory_percent = memory[:mem_used].to_f / memory[:total] * 100
|
30
|
+
swapping = memory[:swapping?]
|
31
|
+
ftag = "#{CLI.bold}%15s#{CLI.reset}:"
|
32
|
+
hist_mem = profile[:memory_hist][:mem_used]
|
33
|
+
|
34
|
+
puts
|
35
|
+
puts "#{CLI.bold}System Information#{CLI.reset}"
|
36
|
+
puts "#{ftag} #{platform} (#{profile[:cpe]})" % "OS"
|
37
|
+
puts "#{ftag} #{profile[:arch]}" % "Arch"
|
38
|
+
puts "#{ftag} #{profile[:hostname]}" % "Hostname"
|
39
|
+
puts
|
40
|
+
|
41
|
+
puts "#{CLI.bold}CPU Statistics#{CLI.reset}"
|
42
|
+
puts "#{ftag} %d" % ["CPU Count", profile[:cpu][:count]]
|
43
|
+
puts "#{ftag} %d MHz" % ["CPU Speed", profile[:cpu][:speed]]
|
44
|
+
puts
|
45
|
+
|
46
|
+
puts "#{CLI.bold}Memory Statistics#{CLI.reset}"
|
47
|
+
puts "#{ftag} %d MiB" % ["Total RAM", memory[:total]]
|
48
|
+
puts "#{ftag} %d MiB (%2.1f%%)" % ["RAM Used", memory[:mem_used],
|
49
|
+
memory_percent]
|
50
|
+
puts "#{ftag} %d MiB" % ["Swap Used", memory[:swap_used]] if swapping
|
51
|
+
puts "#{ftag} %d%%" % ["Hist. RAM Used", hist_mem] unless hist_mem.nil?
|
52
|
+
puts
|
53
|
+
|
54
|
+
puts "#{CLI.bold}Hard Disk Statistics#{CLI.reset}"
|
55
|
+
puts "#{ftag} %2.1f GB" % ["Disk Used", profile[:disk]]
|
56
|
+
puts
|
57
|
+
|
58
|
+
puts "#{CLI.bold}System Statistics#{CLI.reset}"
|
59
|
+
puts "#{ftag} #{profile[:io][:uptime]}" % "Uptime"
|
60
|
+
puts "#{ftag} #{profile[:io][:wait]}" % "I/O Wait"
|
61
|
+
puts
|
62
|
+
|
63
|
+
puts "#{CLI.bold}IP Information#{CLI.reset}"
|
64
|
+
puts "#{ftag} #{profile[:ip][:public].join(', ')}" % "Public"
|
65
|
+
puts "#{ftag} #{profile[:ip][:private].join(', ')}" % "Private"
|
66
|
+
puts
|
67
|
+
|
68
|
+
puts "#{CLI.bold}MySQL Databases#{CLI.reset}"
|
69
|
+
puts "#{ftag} #{profile[:db][:count]}" % "Number"
|
70
|
+
puts "#{ftag} #{profile[:db][:size]}" % "Total Size"
|
71
|
+
puts
|
72
|
+
|
73
|
+
puts "#{CLI.bold}Libraries#{CLI.reset}"
|
74
|
+
puts "#{ftag} #{profile[:lib][:libc]}" % "LIBC"
|
75
|
+
puts "#{ftag} #{profile[:lib][:perl]}" % "Perl"
|
76
|
+
puts "#{ftag} #{profile[:lib][:python]}" % "Python"
|
77
|
+
puts "#{ftag} #{profile[:lib][:ruby]}" % "Ruby"
|
78
|
+
puts "#{ftag} #{profile[:lib][:php]}" % "PHP"
|
79
|
+
unless profile.warnings.empty?
|
80
|
+
puts
|
81
|
+
print CLI.red + CLI.bold
|
82
|
+
profile.warnings.each { |warning| puts warning }
|
83
|
+
print CLI.reset
|
84
|
+
end
|
85
|
+
|
86
|
+
source_host_ssh.logout!
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
# Public: Provide methods to abstract and simplify interaction with a user via
|
2
|
+
# a command-line application.
|
3
|
+
#
|
4
|
+
# Examples
|
5
|
+
#
|
6
|
+
# # prompt for a question with free-form input
|
7
|
+
# answer = Console.prompt("Question")
|
8
|
+
#
|
9
|
+
# # Print bolded text
|
10
|
+
# puts "#{Console.bold}Bold text#{Console.reset}"
|
11
|
+
module CloudFlock::Interface::CLI::Console extend self
|
12
|
+
# Public: Prompt user for input, allowing for a default answer and a list of
|
13
|
+
# valid responses.
|
14
|
+
#
|
15
|
+
# question - String containing the question to present to the user.
|
16
|
+
# args - Hash containing arguments to control acceptable responses.
|
17
|
+
# (default: {}):
|
18
|
+
# :default_answer - String containing the default answer. If the
|
19
|
+
# default is nil, a non-empty answer MUST be given.
|
20
|
+
# :valid_answers - An Array containing all valid responses.
|
21
|
+
#
|
22
|
+
# Returns a String containing the answer provided by the user.
|
23
|
+
def prompt(question, args = {})
|
24
|
+
default = args[:default_answer].to_s
|
25
|
+
allow_empty = !args[:default_answer].nil?
|
26
|
+
valid = args[:valid_answers] || []
|
27
|
+
|
28
|
+
default_display = default.empty? ? "" : "[%s]" % default.strip
|
29
|
+
question.strip!
|
30
|
+
|
31
|
+
acceptable = false
|
32
|
+
until acceptable
|
33
|
+
printf("%s %s> ", question, default_display)
|
34
|
+
answer = readline.strip
|
35
|
+
|
36
|
+
if answer.empty? && allow_empty
|
37
|
+
acceptable = true
|
38
|
+
elsif valid.empty? && !answer.empty?
|
39
|
+
acceptable = true
|
40
|
+
elsif !(valid.grep(answer)).empty? && !valid.empty?
|
41
|
+
acceptable = true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
answer.empty? ? default.to_s : answer
|
46
|
+
end
|
47
|
+
|
48
|
+
# Public: Wrap Console#prompt but require a Y/N response.
|
49
|
+
#
|
50
|
+
# question - String containing the question to present to the user.
|
51
|
+
# args - Hash containing arguments to control acceptable responses.
|
52
|
+
# (default: {}):
|
53
|
+
# :default_answer - String containing the default answer.
|
54
|
+
#
|
55
|
+
# Returns true or false corresponding to Y or N answer respectively.
|
56
|
+
def prompt_yn(question, args = {})
|
57
|
+
args[:valid] = []
|
58
|
+
answer = nil
|
59
|
+
|
60
|
+
until answer =~ /^[yn]/i
|
61
|
+
answer = prompt(question, args)
|
62
|
+
end
|
63
|
+
|
64
|
+
/^n/i.match(answer).nil?
|
65
|
+
end
|
66
|
+
|
67
|
+
# Public: Render a spinner on the command line and yield to a block,
|
68
|
+
# reporting success if nothing is raised, otherwise reporting failure.
|
69
|
+
#
|
70
|
+
# message - Message to be displayed describing the task being evaluated.
|
71
|
+
# block - Block to be yielded to determine pass or fail.
|
72
|
+
#
|
73
|
+
# Returns the result of the yielded block if successful.
|
74
|
+
# Raises whatever is raised inside the yielded block.
|
75
|
+
def spinner(message, &block)
|
76
|
+
success = nil
|
77
|
+
result = nil
|
78
|
+
|
79
|
+
pre = "\r#{bold}#{white} [#{reset}"
|
80
|
+
post = "#{bold}#{white}] #{reset}#{message}"
|
81
|
+
pre_ok = "\r#{bold}#{white} [#{green} ok "
|
82
|
+
pre_fail = "\r#{bold}#{white} [#{red}fail"
|
83
|
+
|
84
|
+
thread = Thread.new do
|
85
|
+
step = 0
|
86
|
+
spin = [" ", ". ", ".. ", "... ", "....", " ...", " ..", " ."]
|
87
|
+
while success.nil?
|
88
|
+
print "#{pre}#{spin[step % 8]}#{post}"
|
89
|
+
step += 1
|
90
|
+
sleep 0.5
|
91
|
+
end
|
92
|
+
|
93
|
+
if success
|
94
|
+
print "#{pre_ok}#{post}\n"
|
95
|
+
else
|
96
|
+
print "#{pre_fail}#{post}\n"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
begin
|
101
|
+
result = yield
|
102
|
+
success = true
|
103
|
+
thread.join
|
104
|
+
return result
|
105
|
+
rescue
|
106
|
+
success = false
|
107
|
+
thread.join
|
108
|
+
raise
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Public: Generate a reasonably formatted, printable table.
|
113
|
+
#
|
114
|
+
# options - An Array containing Hash objects which contain desired options:
|
115
|
+
# [{:col1 => val1, :col2 => val2}, {:col1 => val3, :col2 => val4}]
|
116
|
+
# labels - A Hash containing key-value pairs to label each key in options.
|
117
|
+
# (default: nil)
|
118
|
+
#
|
119
|
+
# Returns a String containing the grid.
|
120
|
+
# Raises ArgumentError if options is not an Array which contains at least one
|
121
|
+
# element.
|
122
|
+
def build_grid(options, labels = nil)
|
123
|
+
raise ArgumentError unless options.kind_of?(Array) and !options[0].nil?
|
124
|
+
|
125
|
+
if labels.nil?
|
126
|
+
options.unshift(options[0].keys.reduce({}) { |c,e| {e => e.to_s} })
|
127
|
+
else
|
128
|
+
options.unshift(labels)
|
129
|
+
end
|
130
|
+
|
131
|
+
keys = options[0].keys
|
132
|
+
max_lengths = keys.reduce({}) { |c,e| c.merge({e => 0}) }
|
133
|
+
|
134
|
+
options.each do |row|
|
135
|
+
row.each_key do |key|
|
136
|
+
if max_lengths[key] < row[key].to_s.length
|
137
|
+
max_lengths[key] = row[key].to_s.length
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Base width = 3n+1
|
143
|
+
grid_width = (max_lengths.length * 3) + 1
|
144
|
+
|
145
|
+
# Construct rule
|
146
|
+
grid_rule = "+"
|
147
|
+
options[0].each_key { |k| grid_rule << "-" * (max_lengths[k] + 2) + "+" }
|
148
|
+
|
149
|
+
# Construct grid
|
150
|
+
grid = ""
|
151
|
+
grid << grid_rule
|
152
|
+
|
153
|
+
options.each_with_index do |row, idx|
|
154
|
+
grid << "\n|"
|
155
|
+
keys.each do |key|
|
156
|
+
grid << sprintf(" % #{max_lengths[key]}s |", row[key])
|
157
|
+
end
|
158
|
+
|
159
|
+
# Visually separate the labels
|
160
|
+
grid << "\n" + grid_rule if idx == 0
|
161
|
+
end
|
162
|
+
grid << "\n" + grid_rule
|
163
|
+
end
|
164
|
+
|
165
|
+
# Minimal documentation provided for the following functions; terminal
|
166
|
+
# control sequences are well documented; here we are only providing
|
167
|
+
# shorthand.
|
168
|
+
|
169
|
+
# Public: Escape sequence
|
170
|
+
#
|
171
|
+
# Returns a String containing an escaped terminal control sequence.
|
172
|
+
def escape(seq); "\033[#{seq}m"; end
|
173
|
+
|
174
|
+
# Public: Reset terminal control
|
175
|
+
#
|
176
|
+
# Returns a String the 'reset' terminal control sequence.
|
177
|
+
def reset; escape("0"); end
|
178
|
+
|
179
|
+
# Public: Set text bold
|
180
|
+
#
|
181
|
+
# Returns a String the terminal control sequence to set text bold.
|
182
|
+
def bold; escape("1"); end
|
183
|
+
|
184
|
+
# Public: Set text underlined
|
185
|
+
#
|
186
|
+
# Returns a String the terminal control sequence to set text underlined.
|
187
|
+
def underline; escape("4"); end
|
188
|
+
|
189
|
+
# Public: Set text flashing
|
190
|
+
#
|
191
|
+
# Returns a String the terminal control sequence to set text flashing.
|
192
|
+
def annoy; escape("5"); end
|
193
|
+
|
194
|
+
# Public: Set text red
|
195
|
+
#
|
196
|
+
# Returns a String the terminal control sequence to set text red.
|
197
|
+
def red; escape("31"); end
|
198
|
+
|
199
|
+
# Public: Set text green
|
200
|
+
#
|
201
|
+
# Returns a String the terminal control sequence to set text green.
|
202
|
+
def green; escape("32"); end
|
203
|
+
|
204
|
+
# Public: Set text blue
|
205
|
+
#
|
206
|
+
# Returns a String the terminal control sequence to set text blue.
|
207
|
+
def blue; escape("34"); end
|
208
|
+
|
209
|
+
# Public: Set text white
|
210
|
+
#
|
211
|
+
# Returns a String the terminal control sequence to set text white.
|
212
|
+
def white; escape("37"); end
|
213
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module CloudFlock::Interface::CLI::Opts extend self
|
2
|
+
# Internal: Extend the Opts module to provide options specific to the servers
|
3
|
+
# migration CLI utility.
|
4
|
+
#
|
5
|
+
# opts - OptionParser object to which to add options.
|
6
|
+
# options - Hash containing options flags and settings for the application.
|
7
|
+
#
|
8
|
+
# Returns nothing.
|
9
|
+
def argv_servers(opts, options)
|
10
|
+
opts.on('-o', '--opencloud', 'Perform an Open Cloud Servers migration') do
|
11
|
+
options[:function] = :opencloud
|
12
|
+
end
|
13
|
+
opts.on('-s', '--servers', 'Perform a Cloud Servers migration') do
|
14
|
+
options[:function] = :servers
|
15
|
+
end
|
16
|
+
opts.on('-r', '--resume', 'Resume a migration') do
|
17
|
+
options[:resume] = true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
Dir.glob(File.expand_path("../opts/*", __FILE__), &method(:require))
|
3
|
+
|
4
|
+
# Public: The CLI Opts module provides methods to abstract and simplify loading
|
5
|
+
# configuration information, parsing options and providing context to the
|
6
|
+
# application.
|
7
|
+
module CloudFlock::Interface::CLI::Opts extend self
|
8
|
+
CONFIG_LOCATION="~/.flockrc"
|
9
|
+
# Public: Open config files if applicable, overwriting default options with
|
10
|
+
# configuration passed files first, then with any options supplied via the
|
11
|
+
# command line.
|
12
|
+
#
|
13
|
+
# function - String or Symbol containing the name of the function to parse
|
14
|
+
# arguments for, if applicable. (default: '')
|
15
|
+
#
|
16
|
+
# Returns a Hash containing an option to value map.
|
17
|
+
def parse(function = '')
|
18
|
+
options = parse_config_file(CONFIG_LOCATION)
|
19
|
+
|
20
|
+
argv = parse_argv(function)
|
21
|
+
if argv[:config_file].kind_of?(String)
|
22
|
+
options.merge(parse_config_file(argv[:config_file]))
|
23
|
+
end
|
24
|
+
|
25
|
+
options.merge(argv)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Internal: Open and parse a given config file.
|
29
|
+
#
|
30
|
+
# file - String containing path to a configuration file which will be parsed.
|
31
|
+
#
|
32
|
+
# Returns a Hash containing option-value mappings.
|
33
|
+
def parse_config_file(file)
|
34
|
+
options = {}
|
35
|
+
return options if file.nil?
|
36
|
+
|
37
|
+
config_string = ""
|
38
|
+
if File.exists?(File.expand_path(file))
|
39
|
+
config_string = File.open(File.expand_path(file)).read
|
40
|
+
end
|
41
|
+
|
42
|
+
config_string.each_line do |line|
|
43
|
+
line.gsub!(/#.*/, "").strip!
|
44
|
+
next if line.empty?
|
45
|
+
|
46
|
+
opt,value = line.split(/\s*/, 2)
|
47
|
+
options[opt.to_sym] = value
|
48
|
+
end
|
49
|
+
|
50
|
+
options
|
51
|
+
end
|
52
|
+
|
53
|
+
# Internal: Parse and return options passed via the command line.
|
54
|
+
#
|
55
|
+
# function - String or Symbol containing the name of the function to parse
|
56
|
+
# arguments for. This will cause the OptionParser to search for a
|
57
|
+
# argv_function name for the given name of the function.
|
58
|
+
#
|
59
|
+
# Returns a Hash containing an option to value map.
|
60
|
+
def parse_argv(function)
|
61
|
+
options = {}
|
62
|
+
|
63
|
+
optparse = OptionParser.new do |opts|
|
64
|
+
opts.on('-v', '--verbose', 'Be verbose') do
|
65
|
+
options[:verbose] = true
|
66
|
+
end
|
67
|
+
|
68
|
+
opts.on('-c', '--config FILE', 'Load configuration saved from previous' +
|
69
|
+
' session (useful with -r)') do |file|
|
70
|
+
unless File.exists?(File.expand_path(file))
|
71
|
+
puts "Configuration file #{file} does not exist! Exiting."
|
72
|
+
exit
|
73
|
+
end
|
74
|
+
options[:config_file] = File.expand_path(file)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Pull in extra options if applicable
|
78
|
+
function = ("argv_" + function.to_s).to_sym
|
79
|
+
if CloudFlock::Interface::CLI::Opts.respond_to?(function)
|
80
|
+
CloudFlock::Interface::CLI::Opts.send(function, opts, options)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
optparse.parse!
|
84
|
+
|
85
|
+
options
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'fog'
|
2
|
+
module Fog
|
3
|
+
module Compute
|
4
|
+
class RackspaceV2
|
5
|
+
class Server
|
6
|
+
# Place existing server into rescue mode, allowing for offline editing of configuration. The original server's disk is attached to a new instance of the same base image for a period of time to facilitate working within rescue mode. The original server will be autom atically restored after 90 minutes.
|
7
|
+
# @return [Boolean] returns true if call to put server in rescue mode returns success
|
8
|
+
# @raise [Fog::Rackspace::Errors::NotFound] - HTTP 404
|
9
|
+
# @raise [Fog::Rackspace::Errors::BadRequest] - HTTP 400
|
10
|
+
# @raise [Fog::Rackspace::Errors::InternalServerError] - HTTP 500
|
11
|
+
# @raise [Fog::Rackspace::Errors::ServiceError]
|
12
|
+
# @note Rescue mode is only guaranteed to be active for 90 minutes.
|
13
|
+
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/rescue_mode.html
|
14
|
+
# @see #unrescue
|
15
|
+
#
|
16
|
+
# * Status Transition:
|
17
|
+
# * ACTIVE -> PREP_RESCUE -> RESCUE
|
18
|
+
def rescue
|
19
|
+
requires :identity
|
20
|
+
data = service.rescue_server(identity)
|
21
|
+
merge_attributes(data.body)
|
22
|
+
self.state = RESCUE
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
# Remove existing server from rescue mode.
|
27
|
+
# @return [Boolean] returns true if call to remove server from rescue mode returns success
|
28
|
+
# @raise [Fog::Rackspace::Errors::NotFound] - HTTP 404
|
29
|
+
# @raise [Fog::Rackspace::Errors::BadRequest] - HTTP 400
|
30
|
+
# @raise [Fog::Rackspace::Errors::InternalServerError] - HTTP 500
|
31
|
+
# @raise [Fog::Rackspace::Errors::ServiceError]
|
32
|
+
# @note Rescue mode is only guaranteed to be active for 90 minutes.
|
33
|
+
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/exit_rescue_mode.html
|
34
|
+
# @see #rescue
|
35
|
+
#
|
36
|
+
# * Status Transition:
|
37
|
+
# * RESCUE -> PREP_UNRESCUE -> ACTIVE
|
38
|
+
def unrescue
|
39
|
+
requires :identity
|
40
|
+
service.unrescue_server(identity)
|
41
|
+
self.state = ACTIVE
|
42
|
+
true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Real
|
47
|
+
# Puts server into rescue mode
|
48
|
+
# @param [String] server_id id of server to rescue
|
49
|
+
# @return [Excon::Response] response
|
50
|
+
# @raise [Fog::Rackspace::Errors::NotFound] - HTTP 404
|
51
|
+
# @raise [Fog::Rackspace::Errors::BadRequest] - HTTP 400
|
52
|
+
# @raise [Fog::Rackspace::Errors::InternalServerError] - HTTP 500
|
53
|
+
# @raise [Fog::Rackspace::Errors::ServiceError]
|
54
|
+
# @note Rescue mode is only guaranteed to be active for 90 minutes.
|
55
|
+
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/rescue_mode.html
|
56
|
+
#
|
57
|
+
# * Status Transition:
|
58
|
+
# * ACTIVE -> PREP_RESCUE -> RESCUE
|
59
|
+
def rescue_server(server_id)
|
60
|
+
data = {
|
61
|
+
'rescue' => nil
|
62
|
+
}
|
63
|
+
|
64
|
+
request(
|
65
|
+
:body => Fog::JSON.encode(data),
|
66
|
+
:expects => [200],
|
67
|
+
:method => 'POST',
|
68
|
+
:path => "servers/#{server_id}/action"
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Take server out of rescue mode
|
73
|
+
# @param [String] server_id id of server
|
74
|
+
# @return [Excon::Response] response
|
75
|
+
# @raise [Fog::Rackspace::Errors::NotFound] - HTTP 404
|
76
|
+
# @raise [Fog::Rackspace::Errors::BadRequest] - HTTP 400
|
77
|
+
# @raise [Fog::Rackspace::Errors::InternalServerError] - HTTP 500
|
78
|
+
# @raise [Fog::Rackspace::Errors::ServiceError]
|
79
|
+
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/exit_rescue_mode.html
|
80
|
+
#
|
81
|
+
# * Status Transition:
|
82
|
+
# * RESCUE -> PREP_UNRESCUE -> ACTIVE
|
83
|
+
def unrescue_server(server_id)
|
84
|
+
data = {
|
85
|
+
'unrescue' => nil
|
86
|
+
}
|
87
|
+
|
88
|
+
request(
|
89
|
+
:body => Fog::JSON.encode(data),
|
90
|
+
:expects => [202],
|
91
|
+
:method => 'POST',
|
92
|
+
:path => "servers/#{server_id}/action"
|
93
|
+
)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class Mock
|
98
|
+
def rescue_server(server_id)
|
99
|
+
server = self.data[:servers][server_id]
|
100
|
+
server["status"] = "PREP_RESCUE"
|
101
|
+
response(:status => 200)
|
102
|
+
end
|
103
|
+
|
104
|
+
def unrescue_server(server_id)
|
105
|
+
server = self.data[:servers][server_id]
|
106
|
+
server["status"] = "PREP_UNRESCUE"
|
107
|
+
response(:status => 202)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|