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