| Class | BoxGrinder::ElasticHostsPlugin |
| In: |
lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb
lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb |
| Parent: | BasePlugin |
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 96
96: def api_url(path)
97: "#{@plugin_config['ssl'] ? 'https' : 'http'}://#{CGI.escape(@plugin_config['username'])}:#{@plugin_config['password']}@#{@plugin_config['endpoint']}#{path}"
98: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 96
96: def api_url(path)
97: "#{@plugin_config['ssl'] ? 'https' : 'http'}://#{CGI.escape(@plugin_config['username'])}:#{@plugin_config['password']}@#{@plugin_config['endpoint']}#{path}"
98: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 132
132: def compress(data)
133: @log.trace "Compressing #{data.size / 1024} kB chunk of data..."
134:
135: io = StringIO.new
136:
137: writer = Zlib::GzipWriter.new(io, Zlib::DEFAULT_COMPRESSION, Zlib::FINISH)
138: writer.write(data)
139: writer.close
140:
141: @log.trace "Data compressed to #{io.size / 1024} kB."
142:
143: io.string
144: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 132
132: def compress(data)
133: @log.trace "Compressing #{data.size / 1024} kB chunk of data..."
134:
135: io = StringIO.new
136:
137: writer = Zlib::GzipWriter.new(io, Zlib::DEFAULT_COMPRESSION, Zlib::FINISH)
138: writer.write(data)
139: writer.close
140:
141: @log.trace "Data compressed to #{io.size / 1024} kB."
142:
143: io.string
144: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 72
72: def create_remote_disk
73: size = disk_size
74:
75: @log.info "Creating new #{size} GB disk..."
76:
77:
78: body = hash_to_request(
79: 'size' => size * 1024 *1024 * 1024,
80: 'name' => @plugin_config['drive_name']
81: )
82:
83: begin
84: ret = response_to_hash(RestClient.post(api_url('/drives/create'), body))
85:
86:
87: @log.info "Disk created with UUID: #{ret['drive']}."
88: rescue => e
89: @log.error e.info
90: raise PluginError, "An error occured while creating the drive, #{e.message}. See logs for more info."
91: end
92:
93: ret['drive']
94: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 72
72: def create_remote_disk
73: size = disk_size
74:
75: @log.info "Creating new #{size} GB disk..."
76:
77:
78: body = hash_to_request(
79: 'size' => size * 1024 *1024 * 1024,
80: 'name' => @plugin_config['drive_name']
81: )
82:
83: begin
84: ret = response_to_hash(RestClient.post(api_url('/drives/create'), body))
85:
86:
87: @log.info "Disk created with UUID: #{ret['drive']}."
88: rescue => e
89: @log.error e.info
90: raise PluginError, "An error occured while creating the drive, #{e.message}. See logs for more info."
91: end
92:
93: ret['drive']
94: end
Creates the server for previously uploaded disk
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 182
182: def create_server
183: @log.info "Creating new server..."
184:
185: memory = ((is_cloudsigma? and @appliance_config.hardware.memory < 512) ? 512 : @appliance_config.hardware.memory)
186:
187: body = hash_to_request(
188: 'name' => "#{@appliance_config.name}-#{@appliance_config.version}.#{@appliance_config.release}",
189: 'cpu' => @appliance_config.hardware.cpus * 1000, # MHz
190: 'smp' => 'auto',
191: 'mem' => memory,
192: 'persistent' => 'true', # hack
193: 'ide:0:0' => @plugin_config['drive_uuid'],
194: 'boot' => 'ide:0:0',
195: 'nic:0:model' => 'e1000',
196: 'nic:0:dhcp' => 'auto',
197: 'vnc:ip' => 'auto',
198: 'vnc:password' => (0...8).map { (('a'..'z').to_a + ('A'..'Z').to_a)[rand(52)] }.join # 8 character VNC password
199: )
200:
201: begin
202: path = is_cloudsigma? ? '/servers/create' : '/servers/create/stopped'
203: ret = response_to_hash(RestClient.post(api_url(path), body))
204:
205: @log.info "Server was registered with '#{ret['name']}' name as '#{ret['server']}' UUID. Use web UI or API tools to start your server."
206: rescue => e
207: @log.error e.info
208: raise PluginError, "An error occured while creating the server, #{e.message}. See logs for more info."
209: end
210: end
Creates the server for previously uploaded disk
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 182
182: def create_server
183: @log.info "Creating new server..."
184:
185: memory = ((is_cloudsigma? and @appliance_config.hardware.memory < 512) ? 512 : @appliance_config.hardware.memory)
186:
187: body = hash_to_request(
188: 'name' => "#{@appliance_config.name}-#{@appliance_config.version}.#{@appliance_config.release}",
189: 'cpu' => @appliance_config.hardware.cpus * 1000, # MHz
190: 'smp' => 'auto',
191: 'mem' => memory,
192: 'persistent' => 'true', # hack
193: 'ide:0:0' => @plugin_config['drive_uuid'],
194: 'boot' => 'ide:0:0',
195: 'nic:0:model' => 'e1000',
196: 'nic:0:dhcp' => 'auto',
197: 'vnc:ip' => 'auto',
198: 'vnc:password' => (0...8).map { (('a'..'z').to_a + ('A'..'Z').to_a)[rand(52)] }.join # 8 character VNC password
199: )
200:
201: begin
202: path = is_cloudsigma? ? '/servers/create' : '/servers/create/stopped'
203: ret = response_to_hash(RestClient.post(api_url(path), body))
204:
205: @log.info "Server was registered with '#{ret['name']}' name as '#{ret['server']}' UUID. Use web UI or API tools to start your server."
206: rescue => e
207: @log.error e.info
208: raise PluginError, "An error occured while creating the server, #{e.message}. See logs for more info."
209: end
210: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 46
46: def disk_size
47: size = 0
48: @appliance_config.hardware.partitions.each_value { |partition| size += partition['size'] }
49: size
50: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 46
46: def disk_size
47: size = 0
48: @appliance_config.hardware.partitions.each_value { |partition| size += partition['size'] }
49: size
50: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 41
41: def execute
42: upload
43: create_server
44: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 41
41: def execute
42: upload
43: create_server
44: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 52
52: def hash_to_request(h)
53: body = ""
54:
55: h.each do |k, v|
56: body << "#{k} #{v.to_s}\n"
57: end
58:
59: body
60: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 52
52: def hash_to_request(h)
53: body = ""
54:
55: h.each do |k, v|
56: body << "#{k} #{v.to_s}\n"
57: end
58:
59: body
60: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 177
177: def is_cloudsigma?
178: !@plugin_config['endpoint'].match(/cloudsigma\.com$/).nil?
179: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 177
177: def is_cloudsigma?
178: !@plugin_config['endpoint'].match(/cloudsigma\.com$/).nil?
179: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 62
62: def response_to_hash(r)
63: h = {}
64:
65: r.each_line do |l|
66: h[$1] = $2 if l =~ /(\w+) (.*)/
67: end
68:
69: h
70: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 62
62: def response_to_hash(r)
63: h = {}
64:
65: r.each_line do |l|
66: h[$1] = $2 if l =~ /(\w+) (.*)/
67: end
68:
69: h
70: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 100
100: def upload
101: @log.info "Uploading appliance..."
102:
103: # Create the disk with specific size or use already existing
104: @plugin_config['drive_uuid'] = create_remote_disk unless @plugin_config['drive_uuid']
105:
106: upload_chunks
107:
108: @log.info "Appliance uploaded."
109: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 100
100: def upload
101: @log.info "Uploading appliance..."
102:
103: # Create the disk with specific size or use already existing
104: @plugin_config['drive_uuid'] = create_remote_disk unless @plugin_config['drive_uuid']
105:
106: upload_chunks
107:
108: @log.info "Appliance uploaded."
109: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 146
146: def upload_chunk(data, part)
147: try = 1
148:
149: url = api_url("/drives/#{@plugin_config['drive_uuid']}/write/#{@step * part}")
150:
151: begin
152: @log.info "Uploading part #{part+1}..."
153:
154: headers = {:content_type => "application/octet-stream"}
155: headers['Content-Encoding'] = 'gzip' unless is_cloudsigma?
156:
157: RestClient.post url,
158: data,
159: headers
160:
161: @log.info "Part #{part+1} uploaded."
162: rescue => e
163: @log.warn "An error occured while uploading #{part} chunk, #{e.message}"
164: try += 1
165:
166: unless try > @plugin_config['retry']
167: # Let's sleep for specified amount of time
168: sleep @plugin_config['wait']
169: retry
170: else
171: @log.error e.info
172: raise PluginError, "Couldn't upload appliance, #{e.message}."
173: end
174: end
175: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 146
146: def upload_chunk(data, part)
147: try = 1
148:
149: url = api_url("/drives/#{@plugin_config['drive_uuid']}/write/#{@step * part}")
150:
151: begin
152: @log.info "Uploading part #{part+1}..."
153:
154: headers = {:content_type => "application/octet-stream"}
155: headers['Content-Encoding'] = 'gzip' unless is_cloudsigma?
156:
157: RestClient.post url,
158: data,
159: headers
160:
161: @log.info "Part #{part+1} uploaded."
162: rescue => e
163: @log.warn "An error occured while uploading #{part} chunk, #{e.message}"
164: try += 1
165:
166: unless try > @plugin_config['retry']
167: # Let's sleep for specified amount of time
168: sleep @plugin_config['wait']
169: retry
170: else
171: @log.error e.info
172: raise PluginError, "Couldn't upload appliance, #{e.message}."
173: end
174: end
175: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 111
111: def upload_chunks
112: @step = @plugin_config['chunk'] * 1024 * 1024 # in bytes
113: part = @plugin_config['start_part']
114:
115: @log.info "Uploading disk in #{disk_size * 1024 / @plugin_config['chunk']} parts."
116:
117: File.open(@previous_deliverables.disk, 'rb') do |f|
118: while !f.eof?
119: f.seek(part * @step, File::SEEK_SET)
120:
121: data = f.read(@step)
122: data = compress(data) unless is_cloudsigma?
123: upload_chunk(data, part)
124:
125: part += 1
126: end
127: end
128:
129: @log.info "Appliance #{@appliance_config.name} uploaded to drive with UUID #{@plugin_config['drive_uuid']}."
130: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 111
111: def upload_chunks
112: @step = @plugin_config['chunk'] * 1024 * 1024 # in bytes
113: part = @plugin_config['start_part']
114:
115: @log.info "Uploading disk in #{disk_size * 1024 / @plugin_config['chunk']} parts."
116:
117: File.open(@previous_deliverables.disk, 'rb') do |f|
118: while !f.eof?
119: f.seek(part * @step, File::SEEK_SET)
120:
121: data = f.read(@step)
122: data = compress(data) unless is_cloudsigma?
123: upload_chunk(data, part)
124:
125: part += 1
126: end
127: end
128:
129: @log.info "Appliance #{@appliance_config.name} uploaded to drive with UUID #{@plugin_config['drive_uuid']}."
130: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 29
29: def validate
30: set_default_config_value('chunk', 64) # chunk size in MB
31: set_default_config_value('start_part', 0) # part number to start uploading
32: set_default_config_value('wait', 5) # wait time before retrying upload
33: set_default_config_value('retry', 3) # number of retries
34: set_default_config_value('ssl', false) # use SSL?
35: set_default_config_value('drive_name', @appliance_config.name)
36:
37: validate_plugin_config(['endpoint', 'username', 'password'], 'http://boxgrinder.org/tutorials/boxgrinder-build-plugins/#ElasticHosts_Delivery_Plugin')
38: raise PluginValidationError, "You can use ElasticHosts plugin with base appliances (appliances created with operating system plugins) only, see http://boxgrinder.org/tutorials/boxgrinder-build-plugins/#ElasticHosts_Delivery_Plugin." unless @previous_plugin_info[:type] == :os
39: end
# File lib/boxgrinder-build/plugins/delivery/elastichosts/elastichosts-plugin.rb, line 29
29: def validate
30: set_default_config_value('chunk', 64) # chunk size in MB
31: set_default_config_value('start_part', 0) # part number to start uploading
32: set_default_config_value('wait', 5) # wait time before retrying upload
33: set_default_config_value('retry', 3) # number of retries
34: set_default_config_value('ssl', false) # use SSL?
35: set_default_config_value('drive_name', @appliance_config.name)
36:
37: validate_plugin_config(['endpoint', 'username', 'password'], 'http://boxgrinder.org/tutorials/boxgrinder-build-plugins/#ElasticHosts_Delivery_Plugin')
38: raise PluginValidationError, "You can use ElasticHosts plugin with base appliances (appliances created with operating system plugins) only, see http://boxgrinder.org/tutorials/boxgrinder-build-plugins/#ElasticHosts_Delivery_Plugin." unless @previous_plugin_info[:type] == :os
39: end