Class: Awscli::EC2::EC2

Inherits:
Object
  • Object
show all
Defined in:
lib/awscli/ec2.rb

Instance Method Summary collapse

Constructor Details

#initialize(connection) ⇒ EC2

initialize ec2 class object params:

connection: Awscli::Connection.new.request_ec2
extra options hash


10
11
12
# File 'lib/awscli/ec2.rb', line 10

def initialize(connection)
  @conn = connection
end

Instance Method Details

#create_instance(options) ⇒ Object

create a single instance with options passed



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/awscli/ec2.rb', line 74

def create_instance(options)
  #validate required options
  puts 'Validating Options ...'
  abort "Invalid Key: #{options[:key_name]}" unless @conn.key_pairs.get(options[:key_name])
  options[:groups].each do |sg|
    abort "Invalid Group: #{sg}" unless @conn.security_groups.get(sg)
  end
  abort "Invalid AMI: #{options[:image_id]}" unless @conn.images.get(options[:image_id])
  abort "Invalid Instance Flavor: #{options[:flavor_id]}" unless @conn.flavors.get(options[:flavor_id])
  #validate optional options
  if options[:availability_zone]
    available_zones = @conn.describe_availability_zones.body['availabilityZoneInfo'].map { |az| az['zoneName'] }
    abort "Invalid AvailabilityZone: #{options[:availability_zone]}" unless available_zones.include?(options[:availability_zone])
  end
  opts = Marshal.load(Marshal.dump(options))
  block_device_mapping = Array.new
  #validate block device mapping and parse it to a hash understandable by fog
  if options[:block_device_mapping]
    options[:block_device_mapping].each do |group|
      mapping = Hash.new
      #parse options
      abort "Invalid block device mapping format, expecting 'devicename=blockdevice' format" unless group =~ /\S=\S/
      device_name, block_device = group.split("=")
      abort "Invalid device name, expecting '/dev/sd[a-z]'" unless device_name =~ /^\/dev\/(sd[a-z][0-9]|sd[a-z])$/
      abort "Invalid block device format, expecting 'ephemeral[0..3]|none|[snapshot-id]:[volume-size]:[true|false]:[standard|io1[:iops]]'" unless block_device =~ /^(snap-.*|ephemeral\w{1,3}|none|:.*)$/
      mapping['DeviceName'] = device_name
      case block_device
      when 'none'
        mapping['Ebs.NoDevice'] = 'true'
      when /ephemeral/
        mapping['VirtualName'] = block_device
      when /snap-.*|:.*/
        snapshot_id, volume_size, delete_on_termination, volume_type, iops = block_device.split(":")

        mapping['Ebs.SnapshotId'] = snapshot_id if !snapshot_id.nil? && !snapshot_id.empty?
        mapping['Ebs.VolumeSize'] = volume_size if !volume_size.nil? && !volume_size.empty?
        mapping['Ebs.DeleteOnTermination'] = delete_on_termination if !delete_on_termination.nil? && !delete_on_termination.empty?
      else
        abort 'Cannot validate block_device'
      end
      block_device_mapping << mapping
    end
  end
  if block_devices = opts.delete(:block_device_mapping)
    opts.merge!(:block_device_mapping => block_device_mapping)
  end
  wait_for_server = options[:wait_for]
  opts.reject! { |k| k == 'wait_for' }
  count = options[:count]
  opts.reject! { |k| k == 'count' }
  puts 'Validating Options ... OK'
  servers = Array.new
  puts "Creating #{count} Server(s) ..."
  count.times { servers << @conn.servers.create(opts) }
  #wait for server to get created and return public_dns
  if wait_for_server
    if count == 1
      print 'Waiting for server to get created'
      servers.first.wait_for { print "."; ready? }
      puts
      puts "Server dns_name: #{servers.first.dns_name}"
    else
      print 'Waiting for servers to get created'
      servers.each do |s|
        s.wait_for { print '.'; ready? }
      end
      puts
      puts 'Servers dns_name: '
      servers.each do |s|
        puts s.dns_name
      end
    end
  end
end

#describe_instance_attribute(instance_id, request) ⇒ Object

describe instance attributes - returns information about an attribute of an instance. You can get information

only one attribute per call.
Available attributes to request: instanceType, kernel, ramdisk, userData, disableApiTermination, instanceInitiatedShutdownBehavior,
  rootDeviceName, blockDeviceMapping, sourceDestCheck, groupSet


29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/awscli/ec2.rb', line 29

def describe_instance_attribute(instance_id, request)
  valid_requests = %w(architecture ami_launch_index availability_zone block_device_mapping network_interfaces client_token
    dns_name ebs_optimized groups flavor_id iam_instance_profile image_id instance_initiated_shutdown_behavior
    kernel_id key_name created_at monitoring placement_group platform private_dns_name private_ip_address
    public_ip_address ramdisk_id root_device_name root_device_type security_group_ids state state_reason subnet_id
    tenancy tags user_data vpc_id volumes username)
  #more options
  #:monitor=, :username=, :private_key=, :private_key_path=, :public_key=, :public_key_path=, :username, :private_key_path, :private_key, :public_key_path, :public_key, :scp, :scp_upload, :scp_download, :ssh, :ssh_port, :sshable?
  response = @conn.servers.get(instance_id)
  abort "Invalid Attribute, available attributes to request: #{valid_requests}" unless valid_requests.include?(request)
  abort "InstanceId Not found :#{instance_id}, Available instnaces #{@conn.servers.map { |x| x.id }}" unless response
  puts "#{request}: #{response.send(request)}"
end

#describe_instance_status(instance_id) ⇒ Object

describe instance status



150
151
152
153
154
# File 'lib/awscli/ec2.rb', line 150

def describe_instance_status(instance_id)
  response = @conn.servers.get(instance_id)
  abort "InstanceId Not found :#{instance_id}" unless response
  puts "Instance #{instance_id} State: #{response.state}"
end

#get_console_output(instance_id) ⇒ Object

get the console_output from instance



224
225
226
227
228
# File 'lib/awscli/ec2.rb', line 224

def get_console_output(instance_id)
  response = @conn.get_console_output(instance_id)
  output = response.data['output']
  output.nil? ? puts('No console output attached yet!') : puts(output)
end

#list_flavorsObject

list available instance types



21
22
23
# File 'lib/awscli/ec2.rb', line 21

def list_flavors
  @conn.flavors.table
end

#list_instancesObject

list instances from a specified region in a tabular format



15
16
17
18
# File 'lib/awscli/ec2.rb', line 15

def list_instances
  @conn.servers.table([:id, :dns_name, :flavor_id, :groups, :image_id, :key_name, :private_ip_address,
    :public_ip_address, :root_device_type, :security_group_ids, :state, :tags])
end

#modify_instance_attribute(instance_id, attributename, attributevalue) ⇒ Object

modifies an attribute of an instance



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/awscli/ec2.rb', line 44

def modify_instance_attribute(instance_id, attributename, attributevalue)
  attrs_lookup = {
    'isize' => 'InstanceType',
    'kernel' => 'Kernel',
    'ramdisk' => 'Ramdisk',
    'userdata' => 'UserData',
    'disable_api_term' => 'DisableApiTermination',
    'inst_shutdown_beh' => 'InstanceInitiatedShutdownBehavior',
    'source_dest_check' => 'SourceDestCheck',
    'group_id' => 'GroupId'
  }
  valid_attributes = %w(InstanceType Kernel Ramdisk UserData DisableApiTermination InstanceInitiatedShutdownBehavior SourceDestCheck GroupId)
  response = @conn.servers.get(instance_id)
  abort "InstanceId Not found :#{instance_id}, Available instnaces #{@conn.servers.map { |x| x.id }}" unless response
  abort "Instance should be in stopped state to modify its attributes" if response.state != 'stopped'
  puts "#{instance_id}, #{attributename}, #{attributevalue}"
  if attrs_lookup[attributename] == 'GroupId' #handle groupid which is array
    puts "#{instance_id}, #{attrs_lookup[attributename]} => #{attributevalue}"
    @conn.modify_instance_attribute(instance_id, attrs_lookup[attributename] => attributevalue)
  else
    puts "#{instance_id}, #{attrs_lookup[attributename]}.Value => #{attributevalue}"
    @conn.modify_instance_attribute(instance_id, "#{attrs_lookup[attributename]}.Value" => attributevalue)
  end
end

#reboot_instance(instance_id) ⇒ Object

@conn.server.get(instance_id).(:reboot, :save, :setup, :start, :stop) reboot an instance



162
163
164
165
166
167
# File 'lib/awscli/ec2.rb', line 162

def reboot_instance(instance_id)
  response = @conn.servers.get(instance_id)
  abort "InstanceId Not found :#{instance_id}" unless response
  response.reboot
  puts "Rebooting Instance: #{instance_id}"
end

#start_instance(instance_id) ⇒ Object

stop a running isntance



179
180
181
182
183
184
185
# File 'lib/awscli/ec2.rb', line 179

def start_instance(instance_id)
  response = @conn.servers.get(instance_id)
  abort "InstanceId Not found :#{instance_id}" unless response
  abort 'Instance should be stopped to start it' if response.state != 'stopped'
  response.start
  puts "Starting Instance: #{instance_id}"
end

#stop_instance(instance_id) ⇒ Object

start a stopped instance



170
171
172
173
174
175
176
# File 'lib/awscli/ec2.rb', line 170

def stop_instance(instance_id)
  response = @conn.servers.get(instance_id)
  abort "InstanceId Not found :#{instance_id}" unless response
  abort 'Instance should be in running to stop it' if response.state != 'running'
  response.stop
  puts "Stopped Instance: #{instance_id}"
end

#terminate_instance(instance_id) ⇒ Object

terminates an instance



188
189
190
191
192
193
194
195
196
197
# File 'lib/awscli/ec2.rb', line 188

def terminate_instance(instance_id)
  response = @conn.servers.get(instance_id)
  abort "InstanceId Not found :#{instance_id}" unless response
  unless response.state == 'terminated'
    response.destroy
    puts "Terminated Instance: #{instance_id}"
  else
    puts 'Instance is already in terminated state'
  end
end

#terminate_instances(delete_attached_volumes = false) ⇒ Object

terminates all the instances that are running



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/awscli/ec2.rb', line 200

def terminate_instances(delete_attached_volumes = false)
  block_mappings = []
  if agree('Are you sure want to delete all the servers that are running ?  ')
    @conn.servers.all.each do |server|
      server.destroy if server.state == 'running' || server.state == 'stopped'
      block_mappings << server.block_device_mapping
    end
  end
  if delete_attached_volumes
    if agree('Are you sure you want to delete the volumes attached to the instance as well?  ')
      unless block_mappings.length == 0
        block_mappings.each do |server|
          server.each do |map|
            vol = @conn.volumes.get(map['volumeId'])
            vol.wait_for { vol.state == 'available' }
            vol.destroy if map['deleteOnTermination'] != 'true'
          end
        end
      end
    end
  end
end