Class BoxGrinder::EBSPlugin
In: lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb
lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb
Parent: BasePlugin

Methods

Constants

KERNELS = { 'us-east-1' => { 'fedora' => { '14' => { 'i386' => {:aki => 'aki-407d9529'}, 'x86_64' => {:aki => 'aki-427d952b'}
KERNELS = { 'us-east-1' => { 'fedora' => { '14' => { 'i386' => {:aki => 'aki-407d9529'}, 'x86_64' => {:aki => 'aki-427d952b'}

Public Instance methods

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 260
260:     def adjust_fstab(ebs_mount_dir)
261:       @exec_helper.execute("cat #{ebs_mount_dir}/etc/fstab | grep -v '/mnt' | grep -v '/data' | grep -v 'swap' > #{ebs_mount_dir}/etc/fstab.new")
262:       @exec_helper.execute("mv #{ebs_mount_dir}/etc/fstab.new #{ebs_mount_dir}/etc/fstab")
263:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 260
260:     def adjust_fstab(ebs_mount_dir)
261:       @exec_helper.execute("cat #{ebs_mount_dir}/etc/fstab | grep -v '/mnt' | grep -v '/data' | grep -v 'swap' > #{ebs_mount_dir}/etc/fstab.new")
262:       @exec_helper.execute("mv #{ebs_mount_dir}/etc/fstab.new #{ebs_mount_dir}/etc/fstab")
263:     end

[Source]

    # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 78
78:     def after_init
79:       begin
80:         @current_avaibility_zone = open('http://169.254.169.254/latest/meta-data/placement/availability-zone').string
81:       rescue
82:         @current_avaibility_zone = nil
83:       end
84: 
85:       set_default_config_value('availability_zone', @current_avaibility_zone)
86:       set_default_config_value('delete_on_termination', true)
87: 
88:       register_supported_os('fedora', ['13', '14'])
89:     end

[Source]

    # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 78
78:     def after_init
79:       begin
80:         @current_avaibility_zone = open('http://169.254.169.254/latest/meta-data/placement/availability-zone').string
81:       rescue
82:         @current_avaibility_zone = nil
83:       end
84: 
85:       set_default_config_value('availability_zone', @current_avaibility_zone)
86:       set_default_config_value('delete_on_termination', true)
87: 
88:       register_supported_os('fedora', ['13', '14'])
89:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 250
250:     def already_registered?(name)
251:       images = @ec2.describe_images(:owner_id => @plugin_config['account_number'].to_s.gsub(/-/, ''))
252: 
253:       return false if images.nil? or images['imagesSet'].nil?
254: 
255:       images['imagesSet']['item'].each { |image| return image['imageId'] if image['name'] == name }
256: 
257:       false
258:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 250
250:     def already_registered?(name)
251:       images = @ec2.describe_images(:owner_id => @plugin_config['account_number'].to_s.gsub(/-/, ''))
252: 
253:       return false if images.nil? or images['imagesSet'].nil?
254: 
255:       images['imagesSet']['item'].each { |image| return image['imageId'] if image['name'] == name }
256: 
257:       false
258:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 283
283:     def device_for_suffix(suffix)
284:       return "/dev/sd#{suffix}" if File.exists?("/dev/sd#{suffix}")
285:       return "/dev/xvd#{suffix}" if File.exists?("/dev/xvd#{suffix}")
286: 
287:       raise "Not found device for suffix #{suffix}"
288:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 283
283:     def device_for_suffix(suffix)
284:       return "/dev/sd#{suffix}" if File.exists?("/dev/sd#{suffix}")
285:       return "/dev/xvd#{suffix}" if File.exists?("/dev/xvd#{suffix}")
286: 
287:       raise "Not found device for suffix #{suffix}"
288:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 91
 91:     def execute(type = :ebs)
 92:       validate_plugin_config(['access_key', 'secret_access_key', 'account_number'], 'http://community.jboss.org/docs/DOC-15921')
 93: 
 94:       raise "You try to run this plugin on invalid platform. You can run EBS delivery plugin only on EC2." unless valid_platform?
 95:       raise "You can only convert to EBS type AMI appliances converted to EC2 format. Use '-p ec2' switch. For more info about EC2 plugin see http://community.jboss.org/docs/DOC-15527." unless @previous_plugin_info[:name] == :ec2
 96:       raise "You selected #{@plugin_config['availability_zone']} avaibility zone, but your instance is running in #{@current_avaibility_zone} zone. Please change avaibility zone in plugin configuration file to #{@current_avaibility_zone} (see http://community.jboss.org/docs/DOC-15921) or use another instance in #{@plugin_config['availability_zone']} zone to create your EBS AMI." if @plugin_config['availability_zone'] != @current_avaibility_zone
 97: 
 98:       unless is_supported_os?
 99:         @log.error "EBS delivery plugin supports following operating systems: #{supported_oses}. Your OS is #{@appliance_config.os.name} #{@appliance_config.os.version}."
100:         return
101:       end
102: 
103:       ebs_appliance_description = "#{@appliance_config.summary} | Appliance version #{@appliance_config.version}.#{@appliance_config.release} | #{@appliance_config.hardware.arch} architecture"
104:       ebs_appliance_name        = "#{@appliance_config.name}/#{@appliance_config.os.name}/#{@appliance_config.os.version}/#{@appliance_config.version}.#{@appliance_config.release}/#{@appliance_config.hardware.arch}"
105: 
106:       @ec2                      = AWS::EC2::Base.new(:access_key_id => @plugin_config['access_key'], :secret_access_key => @plugin_config['secret_access_key'])
107: 
108:       @log.debug "Checking if appliance is already registered..."
109: 
110:       ami_id                    = already_registered?(ebs_appliance_name)
111: 
112:       if ami_id
113:         @log.warn "EBS AMI '#{ebs_appliance_name}' is already registered as '#{ami_id}'."
114:         return
115:       end
116: 
117:       @log.info "Creating new EBS volume..."
118: 
119:       size                      = 0
120: 
121:       @appliance_config.hardware.partitions.each_value { |partition| size += partition['size'] }
122: 
123:       # create_volume with 10GB size
124:       volume_id                 = @ec2.create_volume(:size => size.to_s, :availability_zone => @plugin_config['availability_zone'])['volumeId']
125: 
126:       @log.debug "Volume #{volume_id} created."
127:       @log.debug "Waiting for EBS volume #{volume_id} to be available..."
128: 
129:       # wait fo volume to be created
130:       wait_for_volume_status('available', volume_id)
131: 
132:       # get first free device to mount the volume
133:       suffix                    = free_device_suffix
134: 
135:       @log.trace "Got free device suffix: '#{suffix}'"
136:       @log.trace "Reading current instance id..."
137: 
138:       # read current instance id
139:       instance_id               = open('http://169.254.169.254/latest/meta-data/instance-id').string
140: 
141:       @log.trace "Got: #{instance_id}"
142:       @log.info "Attaching created volume..."
143: 
144:       # attach the volume to current host
145:       @ec2.attach_volume(:device => "/dev/sd#{suffix}", :volume_id => volume_id, :instance_id => instance_id)
146: 
147:       @log.debug "Waiting for EBS volume to be attached..."
148: 
149:       # wait for volume to be attached
150:       wait_for_volume_status('in-use', volume_id)
151: 
152:       sleep 5 # let's wait to discover the attached volume by OS 
153: 
154:       @log.info "Copying data to EBS volume..."
155: 
156:       ec2_disk_mount_dir        = "#{@dir.tmp}/ec2-#{rand(9999999999).to_s.center(10, rand(9).to_s)}"
157:       ebs_disk_mount_dir        = "#{@dir.tmp}/ebs-#{rand(9999999999).to_s.center(10, rand(9).to_s)}"
158: 
159:       FileUtils.mkdir_p(ec2_disk_mount_dir)
160:       FileUtils.mkdir_p(ebs_disk_mount_dir)
161: 
162:       begin
163:         ec2_mounts = @image_helper.mount_image(@previous_deliverables.disk, ec2_disk_mount_dir)
164:       rescue => e
165:         @log.debug e
166:         raise "Error while mounting image. See logs for more info"
167:       end
168: 
169:       @log.debug "Creating filesystem on volume..."
170: 
171:       @image_helper.create_filesystem(device_for_suffix(suffix))
172:       @exec_helper.execute("mount #{device_for_suffix(suffix)} #{ebs_disk_mount_dir}")
173: 
174:       @log.debug "Syncing files..."
175: 
176:       @image_helper.sync_files(ec2_disk_mount_dir, ebs_disk_mount_dir)
177: 
178:       @log.debug "Adjusting /etc/fstab..."
179: 
180:       adjust_fstab(ebs_disk_mount_dir)
181: 
182:       @exec_helper.execute("umount #{ebs_disk_mount_dir}")
183:       @image_helper.umount_image(@previous_deliverables.disk, ec2_disk_mount_dir, ec2_mounts)
184: 
185:       FileUtils.rm_rf(ebs_disk_mount_dir)
186:       FileUtils.rm_rf(ec2_disk_mount_dir)
187: 
188:       @log.debug "Detaching EBS volume..."
189: 
190:       @ec2.detach_volume(:device => "/dev/sd#{suffix}", :volume_id => volume_id, :instance_id => instance_id)
191: 
192:       @log.debug "Waiting for EBS volume to be available..."
193: 
194:       wait_for_volume_status('available', volume_id)
195: 
196:       @log.info "Creating snapshot from EBS volume..."
197: 
198:       snapshot_id               = @ec2.create_snapshot(
199:           :volume_id   => volume_id,
200:           :description => ebs_appliance_description)['snapshotId']
201: 
202:       @log.debug "Waiting for snapshot #{snapshot_id} to be completed..."
203: 
204:       wait_for_snapshot_status('completed', snapshot_id)
205: 
206:       @log.debug "Deleting temporary EBS volume..."
207: 
208:       @ec2.delete_volume(:volume_id => volume_id)
209: 
210:       @log.info "Registering image..."
211: 
212:       region                    = @current_avaibility_zone.scan(/((\w+)-(\w+)-(\d+))/).flatten.first
213:       image_id                  = @ec2.register_image(
214:           :block_device_mapping   => [{
215:                                           :device_name               => '/dev/sda1',
216:                                           :ebs_snapshot_id           => snapshot_id,
217:                                           :ebs_delete_on_termination => @plugin_config['delete_on_termination']
218:                                       },
219:                                       {
220:                                           :device_name               => '/dev/sdb',
221:                                           :virtual_name              => 'ephemeral0'
222:                                       },
223:                                       {
224:                                           :device_name               => '/dev/sdc',
225:                                           :virtual_name              => 'ephemeral1'
226:                                       },
227:                                       {
228:                                           :device_name               => '/dev/sdd',
229:                                           :virtual_name              => 'ephemeral2'
230:                                       },
231:                                       {
232:                                           :device_name               => '/dev/sde',
233:                                           :virtual_name              => 'ephemeral3'
234:                                       }],
235:           :root_device_name       => '/dev/sda1',
236:           :architecture           => @appliance_config.hardware.base_arch,
237:           :kernel_id              => KERNELS[region][@appliance_config.os.name][@appliance_config.os.version][@appliance_config.hardware.base_arch][:aki],
238:           :name                   => ebs_appliance_name,
239:           :description            => ebs_appliance_description)['imageId']
240: 
241:       @log.info "EBS AMI registered: #{image_id}"
242:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 91
 91:     def execute(type = :ebs)
 92:       validate_plugin_config(['access_key', 'secret_access_key', 'account_number'], 'http://community.jboss.org/docs/DOC-15921')
 93: 
 94:       raise "You try to run this plugin on invalid platform. You can run EBS delivery plugin only on EC2." unless valid_platform?
 95:       raise "You can only convert to EBS type AMI appliances converted to EC2 format. Use '-p ec2' switch. For more info about EC2 plugin see http://community.jboss.org/docs/DOC-15527." unless @previous_plugin_info[:name] == :ec2
 96:       raise "You selected #{@plugin_config['availability_zone']} avaibility zone, but your instance is running in #{@current_avaibility_zone} zone. Please change avaibility zone in plugin configuration file to #{@current_avaibility_zone} (see http://community.jboss.org/docs/DOC-15921) or use another instance in #{@plugin_config['availability_zone']} zone to create your EBS AMI." if @plugin_config['availability_zone'] != @current_avaibility_zone
 97: 
 98:       unless is_supported_os?
 99:         @log.error "EBS delivery plugin supports following operating systems: #{supported_oses}. Your OS is #{@appliance_config.os.name} #{@appliance_config.os.version}."
100:         return
101:       end
102: 
103:       ebs_appliance_description = "#{@appliance_config.summary} | Appliance version #{@appliance_config.version}.#{@appliance_config.release} | #{@appliance_config.hardware.arch} architecture"
104:       ebs_appliance_name        = "#{@appliance_config.name}/#{@appliance_config.os.name}/#{@appliance_config.os.version}/#{@appliance_config.version}.#{@appliance_config.release}/#{@appliance_config.hardware.arch}"
105: 
106:       @ec2                      = AWS::EC2::Base.new(:access_key_id => @plugin_config['access_key'], :secret_access_key => @plugin_config['secret_access_key'])
107: 
108:       @log.debug "Checking if appliance is already registered..."
109: 
110:       ami_id                    = already_registered?(ebs_appliance_name)
111: 
112:       if ami_id
113:         @log.warn "EBS AMI '#{ebs_appliance_name}' is already registered as '#{ami_id}'."
114:         return
115:       end
116: 
117:       @log.info "Creating new EBS volume..."
118: 
119:       size                      = 0
120: 
121:       @appliance_config.hardware.partitions.each_value { |partition| size += partition['size'] }
122: 
123:       # create_volume with 10GB size
124:       volume_id                 = @ec2.create_volume(:size => size.to_s, :availability_zone => @plugin_config['availability_zone'])['volumeId']
125: 
126:       @log.debug "Volume #{volume_id} created."
127:       @log.debug "Waiting for EBS volume #{volume_id} to be available..."
128: 
129:       # wait fo volume to be created
130:       wait_for_volume_status('available', volume_id)
131: 
132:       # get first free device to mount the volume
133:       suffix                    = free_device_suffix
134: 
135:       @log.trace "Got free device suffix: '#{suffix}'"
136:       @log.trace "Reading current instance id..."
137: 
138:       # read current instance id
139:       instance_id               = open('http://169.254.169.254/latest/meta-data/instance-id').string
140: 
141:       @log.trace "Got: #{instance_id}"
142:       @log.info "Attaching created volume..."
143: 
144:       # attach the volume to current host
145:       @ec2.attach_volume(:device => "/dev/sd#{suffix}", :volume_id => volume_id, :instance_id => instance_id)
146: 
147:       @log.debug "Waiting for EBS volume to be attached..."
148: 
149:       # wait for volume to be attached
150:       wait_for_volume_status('in-use', volume_id)
151: 
152:       sleep 5 # let's wait to discover the attached volume by OS 
153: 
154:       @log.info "Copying data to EBS volume..."
155: 
156:       ec2_disk_mount_dir        = "#{@dir.tmp}/ec2-#{rand(9999999999).to_s.center(10, rand(9).to_s)}"
157:       ebs_disk_mount_dir        = "#{@dir.tmp}/ebs-#{rand(9999999999).to_s.center(10, rand(9).to_s)}"
158: 
159:       FileUtils.mkdir_p(ec2_disk_mount_dir)
160:       FileUtils.mkdir_p(ebs_disk_mount_dir)
161: 
162:       begin
163:         ec2_mounts = @image_helper.mount_image(@previous_deliverables.disk, ec2_disk_mount_dir)
164:       rescue => e
165:         @log.debug e
166:         raise "Error while mounting image. See logs for more info"
167:       end
168: 
169:       @log.debug "Creating filesystem on volume..."
170: 
171:       @image_helper.create_filesystem(device_for_suffix(suffix))
172:       @exec_helper.execute("mount #{device_for_suffix(suffix)} #{ebs_disk_mount_dir}")
173: 
174:       @log.debug "Syncing files..."
175: 
176:       @image_helper.sync_files(ec2_disk_mount_dir, ebs_disk_mount_dir)
177: 
178:       @log.debug "Adjusting /etc/fstab..."
179: 
180:       adjust_fstab(ebs_disk_mount_dir)
181: 
182:       @exec_helper.execute("umount #{ebs_disk_mount_dir}")
183:       @image_helper.umount_image(@previous_deliverables.disk, ec2_disk_mount_dir, ec2_mounts)
184: 
185:       FileUtils.rm_rf(ebs_disk_mount_dir)
186:       FileUtils.rm_rf(ec2_disk_mount_dir)
187: 
188:       @log.debug "Detaching EBS volume..."
189: 
190:       @ec2.detach_volume(:device => "/dev/sd#{suffix}", :volume_id => volume_id, :instance_id => instance_id)
191: 
192:       @log.debug "Waiting for EBS volume to be available..."
193: 
194:       wait_for_volume_status('available', volume_id)
195: 
196:       @log.info "Creating snapshot from EBS volume..."
197: 
198:       snapshot_id               = @ec2.create_snapshot(
199:           :volume_id   => volume_id,
200:           :description => ebs_appliance_description)['snapshotId']
201: 
202:       @log.debug "Waiting for snapshot #{snapshot_id} to be completed..."
203: 
204:       wait_for_snapshot_status('completed', snapshot_id)
205: 
206:       @log.debug "Deleting temporary EBS volume..."
207: 
208:       @ec2.delete_volume(:volume_id => volume_id)
209: 
210:       @log.info "Registering image..."
211: 
212:       region                    = @current_avaibility_zone.scan(/((\w+)-(\w+)-(\d+))/).flatten.first
213:       image_id                  = @ec2.register_image(
214:           :block_device_mapping   => [{
215:                                           :device_name               => '/dev/sda1',
216:                                           :ebs_snapshot_id           => snapshot_id,
217:                                           :ebs_delete_on_termination => @plugin_config['delete_on_termination']
218:                                       },
219:                                       {
220:                                           :device_name               => '/dev/sdb',
221:                                           :virtual_name              => 'ephemeral0'
222:                                       },
223:                                       {
224:                                           :device_name               => '/dev/sdc',
225:                                           :virtual_name              => 'ephemeral1'
226:                                       },
227:                                       {
228:                                           :device_name               => '/dev/sdd',
229:                                           :virtual_name              => 'ephemeral2'
230:                                       },
231:                                       {
232:                                           :device_name               => '/dev/sde',
233:                                           :virtual_name              => 'ephemeral3'
234:                                       }],
235:           :root_device_name       => '/dev/sda1',
236:           :architecture           => @appliance_config.hardware.base_arch,
237:           :kernel_id              => KERNELS[region][@appliance_config.os.name][@appliance_config.os.version][@appliance_config.hardware.base_arch][:aki],
238:           :name                   => ebs_appliance_name,
239:           :description            => ebs_appliance_description)['imageId']
240: 
241:       @log.info "EBS AMI registered: #{image_id}"
242:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 290
290:     def free_device_suffix
291:       ("f".."p").each do |suffix|
292:         return suffix unless File.exists?("/dev/sd#{suffix}") or File.exists?("/dev/xvd#{suffix}")
293:       end
294: 
295:       raise "Found too many attached devices. Cannot attach EBS volume."
296:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 290
290:     def free_device_suffix
291:       ("f".."p").each do |suffix|
292:         return suffix unless File.exists?("/dev/sd#{suffix}") or File.exists?("/dev/xvd#{suffix}")
293:       end
294: 
295:       raise "Found too many attached devices. Cannot attach EBS volume."
296:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 244
244:     def sync_files(from_dir, to_dir)
245:       @log.debug "Syncing files between #{from_dir} and #{to_dir}..."
246:       @exec_helper.execute "rsync -u -r -a  #{from_dir}/* #{to_dir}"
247:       @log.debug "Sync finished."
248:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 244
244:     def sync_files(from_dir, to_dir)
245:       @log.debug "Syncing files between #{from_dir} and #{to_dir}..."
246:       @exec_helper.execute "rsync -u -r -a  #{from_dir}/* #{to_dir}"
247:       @log.debug "Sync finished."
248:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 298
298:     def valid_platform?
299:       begin
300:         open("http://169.254.169.254/1.0/meta-data/local-ipv4")
301:         true
302:       rescue
303:         false
304:       end
305:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 298
298:     def valid_platform?
299:       begin
300:         open("http://169.254.169.254/1.0/meta-data/local-ipv4")
301:         true
302:       rescue
303:         false
304:       end
305:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 265
265:     def wait_for_snapshot_status(status, snapshot_id)
266:       snapshot = @ec2.describe_snapshots(:snapshot_id => snapshot_id)['snapshotSet']['item'].first
267: 
268:       unless snapshot['status'] == status
269:         sleep 2
270:         wait_for_snapshot_status(status, snapshot_id)
271:       end
272:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 265
265:     def wait_for_snapshot_status(status, snapshot_id)
266:       snapshot = @ec2.describe_snapshots(:snapshot_id => snapshot_id)['snapshotSet']['item'].first
267: 
268:       unless snapshot['status'] == status
269:         sleep 2
270:         wait_for_snapshot_status(status, snapshot_id)
271:       end
272:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 274
274:     def wait_for_volume_status(status, volume_id)
275:       volume = @ec2.describe_volumes(:volume_id => volume_id)['volumeSet']['item'].first
276: 
277:       unless volume['status'] == status
278:         sleep 2
279:         wait_for_volume_status(status, volume_id)
280:       end
281:     end

[Source]

     # File lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb, line 274
274:     def wait_for_volume_status(status, volume_id)
275:       volume = @ec2.describe_volumes(:volume_id => volume_id)['volumeSet']['item'].first
276: 
277:       unless volume['status'] == status
278:         sleep 2
279:         wait_for_volume_status(status, volume_id)
280:       end
281:     end

[Validate]