Class | BoxGrinder::EBSPlugin |
In: |
lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb
lib/boxgrinder-build-ebs-delivery-plugin/ebs-plugin.rb |
Parent: | BasePlugin |
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'} |
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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
# 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