Class: Beaker::AwsSdk
- Inherits:
-
Hypervisor
- Object
- Hypervisor
- Beaker::AwsSdk
- Defined in:
- lib/beaker/hypervisor/aws_sdk.rb
Overview
This is an alternate EC2 driver that implements direct API access using Amazon’s AWS-SDK library: / SDK For Ruby
It is built for full control, to reduce any other layers beyond the pure vendor API.
Direct Known Subclasses
Constant Summary collapse
- ZOMBIE =
anything older than 3 hours is considered a zombie
3
- PING_SECURITY_GROUP_NAME =
'beaker-ping'
Instance Attribute Summary collapse
-
#default_region ⇒ Object
readonly
Returns the value of attribute default_region.
Instance Method Summary collapse
-
#add_ingress_rule(cl, sg_group, cidr_ip, from_port, to_port, protocol = 'tcp') ⇒ void
private
Authorizes connections from certain CIDR to a range of ports.
-
#add_tags ⇒ void
private
Add metadata tags to all instances.
-
#backoff_sleep(tries) ⇒ void
private
Calculates and waits a back-off period based on the number of tries.
-
#cleanup ⇒ void
Cleanup all earlier provisioned hosts on EC2 using the Aws::EC2 library.
- #client(region = default_region) ⇒ Object
-
#configure_hosts ⇒ void
private
Configure /etc/hosts for each node.
-
#create_group(region_or_vpc, ports, sg_cidr_ips = ['0.0.0.0/0']) ⇒ Aws::EC2::SecurityGroup
private
Create a new security group.
-
#create_instance(host, ami_spec, subnet_id) ⇒ void
private
Create an EC2 instance for host, tag it, and return it.
-
#create_new_key_pair(region, pair_name) ⇒ Aws::EC2::KeyPair
Create a new key pair for a given Beaker run.
-
#create_ping_group(region_or_vpc, sg_cidr_ips = ['0.0.0.0/0']) ⇒ Aws::EC2::SecurityGroup
private
Create a new ping enabled security group.
-
#delete_key_pair(region, pair_name) ⇒ Object
private
Deletes a given key pair.
-
#delete_key_pair_all_regions(keypair_name_filter = nil) ⇒ Object
private
Deletes key pairs from all regions.
-
#enable_root(host) ⇒ void
private
Enables root access for a host when username is not root.
-
#enable_root_f5(host) ⇒ Object
private
Enables root access for a host on an f5 platform.
-
#enable_root_netscaler(host) ⇒ Object
private
Enables root access for a host on an netscaler platform.
-
#enable_root_on_hosts ⇒ void
private
Enables root for instances with custom username like ubuntu-amis.
-
#ensure_group(vpc, ports, sg_cidr_ips = ['0.0.0.0/0']) ⇒ Aws::EC2::SecurityGroup
private
Return an existing group, or create new one.
-
#ensure_key_pair(region) ⇒ Aws::EC2::KeyPair
private
Creates the KeyPair for this test run.
-
#ensure_ping_group(vpc, sg_cidr_ips = ['0.0.0.0/0']) ⇒ Aws::EC2::SecurityGroup
private
Return an existing group, or create new one.
-
#etc_hosts_entry(host, interface = :ip) ⇒ String
private
Return a valid /etc/hosts line for a given host.
-
#group_id(ports) ⇒ String
private
Return a reproducable security group identifier based on input ports.
-
#initialize(hosts, options) ⇒ AwsSdk
constructor
Initialize AwsSdk hypervisor driver.
-
#instance_by_id(id) ⇒ Aws::EC2::Types::Instance
Provided an id return an instance object.
-
#instances ⇒ Array<Aws::Ec2::Types::Instance>
Return all instances currently on ec2.
-
#key_name ⇒ String
private
Generate a reusable key name from the local hosts hostname.
-
#key_name_prefix ⇒ String
Generate a key prefix for key pair names.
-
#kill_instances(instances) ⇒ void
Kill all instances.
-
#kill_zombie_volumes ⇒ Object
Destroy any volumes marked ‘available’, INCLUDING THOSE YOU DON’T OWN! Use with care.
-
#kill_zombies(max_age = ZOMBIE, key = key_name) ⇒ Object
Shutdown and destroy ec2 instances idenfitied by key that have been alive longer than ZOMBIE hours.
-
#launch_all_nodes ⇒ void
private
Create EC2 instances for all hosts, tag them, and wait until they’re running.
-
#launch_nodes_on_some_subnet(hosts, subnets, ami_spec, instances_created) ⇒ void
private
For each host, create an EC2 instance in one of the specified subnets and push it onto instances_created.
-
#load_credentials ⇒ Hash<Symbol, String>
private
Return a hash containing AWS credentials.
-
#load_env_credentials(prefix = 'AWS') ⇒ Aws::Credentials
private
Return AWS credentials loaded from environment variables.
-
#load_fog_credentials(dot_fog = '.fog') ⇒ Aws::Credentials
private
Return a hash containing the fog credentials for EC2.
-
#local_user ⇒ String
private
Returns the local user running this tool.
-
#log_instances(key = key_name, status = /running/) ⇒ Object
Print instances to the logger.
-
#modify_network_interface ⇒ void
private
Add correct security groups to hosts network_interface as during the create_instance stage it is too early in process to configure.
-
#my_key_pairs(name_filter = nil) ⇒ Hash{String=>Array[String]}
private
Gets the Beaker user’s keypairs by region.
-
#populate_dns ⇒ void
private
Populate the hosts IP address from the EC2 dns_name.
-
#provision ⇒ void
Provision all hosts on EC2 using the Aws::EC2 API.
-
#public_key ⇒ String
private
Retrieve the public key locally from the executing users ~/.ssh directory.
- #regions ⇒ Object
-
#security_group_by_id(id) ⇒ Aws::EC2::Types::SecurityGroup
Provided an id return a security group object Security object will respond to methods described here: AWS SecurityGroup Object.
-
#security_groups ⇒ Array<Aws::EC2::Types::SecurityGroup>
Return all security groups currently on ec2.
-
#set_hostnames ⇒ @hosts
private
Set the :vmhostname for each host object to be the dns_name, which is accessible publicly.
-
#test_split_install ⇒ Object
Adds port 8143 to host if master, database and dashboard are not on same instance.
-
#vpc_by_id(id) ⇒ Aws::EC2::Types::Vpc
Provided an id return a VPC object.
-
#vpcs ⇒ Array<Aws::EC2::Types::Vpc>
Return all VPCs currently on ec2.
-
#wait_for_status(state_name, instances, &block) ⇒ void
private
Wait until all instances reach the desired state.
-
#wait_for_status_netdev ⇒ void
private
Handles special checks needed for netdev platforms.
Constructor Details
#initialize(hosts, options) ⇒ AwsSdk
Initialize AwsSdk hypervisor driver
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 28 def initialize(hosts, ) @hosts = hosts @options = @logger = [:logger] @default_region = ENV['AWS_REGION'] || 'us-west-2' # Get AWS credentials creds = [:use_fog_credentials] ? load_credentials() : nil config = { :credentials => creds, :logger => Logger.new($stdout), :log_level => :debug, :log_formatter => Aws::Log::Formatter.colored, :retry_limit => 12, :region => ENV['AWS_REGION'] || 'us-west-2' }.delete_if{ |k,v| v.nil? } Aws.config.update(config) @client = {} @client.default_proc = proc do |hash, key| hash[key] = Aws::EC2::Client.new(:region => key) end test_split_install() end |
Instance Attribute Details
#default_region ⇒ Object (readonly)
Returns the value of attribute default_region.
22 23 24 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 22 def default_region @default_region end |
Instance Method Details
#add_ingress_rule(cl, sg_group, cidr_ip, from_port, to_port, protocol = 'tcp') ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Authorizes connections from certain CIDR to a range of ports
1105 1106 1107 1108 1109 1110 1111 1112 1113 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 1105 def add_ingress_rule(cl, sg_group, cidr_ip, from_port, to_port, protocol = 'tcp') cl.( :cidr_ip => cidr_ip, :ip_protocol => protocol, :from_port => from_port, :to_port => to_port, :group_id => sg_group.group_id, ) end |
#add_tags ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Add metadata tags to all instances
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 559 def @hosts.each do |host| instance = host['instance'] # Define tags for the instance @logger.notify("aws-sdk: Add tags for #{host.name}") = [ { :key => 'jenkins_build_url', :value => @options[:jenkins_build_url], }, { :key => 'Name', :value => host.name, }, { :key => 'department', :value => @options[:department], }, { :key => 'project', :value => @options[:project], }, { :key => 'created_by', :value => @options[:created_by], }, ] host[:host_tags].each do |name, val| << { :key => name.to_s, :value => val } end client.( :resources => [instance.instance_id], :tags => .reject { |r| r[:value].nil? }, ) end nil end |
#backoff_sleep(tries) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Calculates and waits a back-off period based on the number of tries
Logs each backupoff time and retry value to the console.
815 816 817 818 819 820 821 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 815 def backoff_sleep(tries) # Exponential with some randomization sleep_time = 2 ** tries @logger.notify("aws-sdk: Sleeping #{sleep_time} seconds for attempt #{tries}.") sleep sleep_time nil end |
#cleanup ⇒ void
This method returns an undefined value.
Cleanup all earlier provisioned hosts on EC2 using the Aws::EC2 library
It goes without saying, but a #cleanup does nothing without a #provision method call first.
126 127 128 129 130 131 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 126 def cleanup # Provisioning should have set the host 'instance' values. kill_instances(@hosts.map{ |h| h['instance'] }.select{ |x| !x.nil? }) delete_key_pair_all_regions() nil end |
#client(region = default_region) ⇒ Object
55 56 57 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 55 def client(region = default_region) @client[region] end |
#configure_hosts ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
f5 hosts are skipped since this isn’t a valid step there
This method returns an undefined value.
Configure /etc/hosts for each node
666 667 668 669 670 671 672 673 674 675 676 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 666 def configure_hosts non_netdev_windows_hosts = @hosts.select{ |h| !(h['platform'] =~ /f5-|netscaler|windows/) } non_netdev_windows_hosts.each do |host| host_entries = non_netdev_windows_hosts.map do |h| h == host ? etc_hosts_entry(h, :private_ip) : etc_hosts_entry(h) end host_entries.unshift "127.0.0.1\tlocalhost localhost.localdomain\n" set_etc_hosts(host, host_entries.join('')) end nil end |
#create_group(region_or_vpc, ports, sg_cidr_ips = ['0.0.0.0/0']) ⇒ Aws::EC2::SecurityGroup
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Create a new security group
Accepts a region or VPC for group creation.
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 1068 def create_group(region_or_vpc, ports, sg_cidr_ips = ['0.0.0.0/0']) name = group_id(ports) @logger.notify("aws-sdk: Creating group #{name} for ports #{ports.to_s}") @logger.notify("aws-sdk: Creating group #{name} with CIDR IPs #{sg_cidr_ips.to_s}") cl = region_or_vpc.is_a?(String) ? client(region_or_vpc) : client params = { :description => "Custom Beaker security group for #{ports.to_a}", :group_name => name, } params[:vpc_id] = region_or_vpc.vpc_id if region_or_vpc.is_a?(Aws::EC2::Types::Vpc) group = cl.create_security_group(params) unless ports.is_a? Set ports = Set.new(ports) end sg_cidr_ips.each do |cidr_ip| ports.each do |port| add_ingress_rule(cl, group, cidr_ip, port, port) end end group end |
#create_instance(host, ami_spec, subnet_id) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Create an EC2 instance for host, tag it, and return it.
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 272 def create_instance(host, ami_spec, subnet_id) amitype = host['vmname'] || host['platform'] amisize = host['amisize'] || 'm1.small' vpc_id = host['vpc_id'] || @options['vpc_id'] || nil host['sg_cidr_ips'] = host['sg_cidr_ips'] || '0.0.0.0/0'; sg_cidr_ips = host['sg_cidr_ips'].split(',') assoc_pub_ip_addr = host['associate_public_ip_address'] if vpc_id && !subnet_id raise RuntimeError, "A subnet_id must be provided with a vpc_id" end if assoc_pub_ip_addr && !subnet_id raise RuntimeError, "A subnet_id must be provided when configuring assoc_pub_ip_addr" end # Use snapshot provided for this host image_type = host['snapshot'] raise RuntimeError, "No snapshot/image_type provided for EC2 provisioning" unless image_type ami = ami_spec[amitype] ami_region = ami[:region] # Main region object for ec2 operations region = ami_region # If we haven't defined a vpc_id then we use the default vpc for the provided region unless vpc_id @logger.notify("aws-sdk: filtering available vpcs in region by 'isDefault'") default_vpcs = client(region).describe_vpcs(:filters => [{:name => 'isDefault', :values => ['true']}]) vpc_id = if default_vpcs.vpcs.empty? nil else default_vpcs.vpcs.first.vpc_id end end # Grab the vpc object based upon provided id vpc = vpc_id ? client(region).describe_vpcs(:vpc_ids => [vpc_id]).vpcs.first : nil # Grab image object image_id = ami[:image][image_type.to_sym] @logger.notify("aws-sdk: Checking image #{image_id} exists and getting its root device") image = client(region).describe_images(:image_ids => [image_id]).images.first raise RuntimeError, "Image not found: #{image_id}" if image.nil? @logger.notify("Image Storage Type: #{image.root_device_type}") # Transform the images block_device_mappings output into a format # ready for a create. block_device_mappings = [] if image.root_device_type == :ebs orig_bdm = image.block_device_mappings @logger.notify("aws-sdk: Image block_device_mappings: #{orig_bdm}") orig_bdm.each do |block_device| block_device_mappings << { :device_name => block_device.device_name, :ebs => { # Change the default size of the root volume. :volume_size => host['volume_size'] || block_device.ebs.volume_size, # This is required to override the images default for # delete_on_termination, forcing all volumes to be deleted once the # instance is terminated. :delete_on_termination => true, } } end end security_group = ensure_group(vpc || region, Beaker::EC2Helper.amiports(host), sg_cidr_ips) #check if ping is enabled ping_security_group = ensure_ping_group(vpc || region, sg_cidr_ips) msg = "aws-sdk: launching %p on %p using %p/%p%s" % [host.name, amitype, amisize, image_type, subnet_id ? ("in %p" % subnet_id) : ''] @logger.notify(msg) config = { :max_count => 1, :min_count => 1, :image_id => image_id, :monitoring => { :enabled => true, }, :key_name => ensure_key_pair(region).key_pairs.first.key_name, :instance_type => amisize, :disable_api_termination => false, :instance_initiated_shutdown_behavior => "terminate", } if assoc_pub_ip_addr # this never gets created, so they end up with # default security group which only allows for # ssh access from outside world which # doesn't work well with remote devices etc. config[:network_interfaces] = [{ :subnet_id => subnet_id, :groups => [security_group.group_id, ping_security_group.group_id], :device_index => 0, :associate_public_ip_address => assoc_pub_ip_addr, }] else config[:subnet_id] = subnet_id end config[:block_device_mappings] = block_device_mappings if image.root_device_type == :ebs reservation = client(region).run_instances(config) reservation.instances.first end |
#create_new_key_pair(region, pair_name) ⇒ Aws::EC2::KeyPair
Create a new key pair for a given Beaker run
944 945 946 947 948 949 950 951 952 953 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 944 def create_new_key_pair(region, pair_name) @logger.debug("aws-sdk: importing new key pair: #{pair_name}") client(region).import_key_pair(:key_name => pair_name, :public_key_material => public_key) begin client(region).wait_until(:key_pair_exists, { :key_names => [pair_name] }, :max_attempts => 5, :delay => 2) rescue Aws::Waiters::Errors::WaiterFailed raise RuntimeError, "AWS key pair #{pair_name} can not be queried, even after import" end end |
#create_ping_group(region_or_vpc, sg_cidr_ips = ['0.0.0.0/0']) ⇒ Aws::EC2::SecurityGroup
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Create a new ping enabled security group
Accepts a region or VPC for group creation.
1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 1033 def create_ping_group(region_or_vpc, sg_cidr_ips = ['0.0.0.0/0']) @logger.notify("aws-sdk: Creating group #{PING_SECURITY_GROUP_NAME}") cl = region_or_vpc.is_a?(String) ? client(region_or_vpc) : client params = { :description => 'Custom Beaker security group to enable ping', :group_name => PING_SECURITY_GROUP_NAME, } params[:vpc_id] = region_or_vpc.vpc_id if region_or_vpc.is_a?(Aws::EC2::Types::Vpc) group = cl.create_security_group(params) sg_cidr_ips.each do |cidr_ip| add_ingress_rule( cl, group, cidr_ip, '8', # 8 == ICMPv4 ECHO request '-1', # -1 == All ICMP codes 'icmp', ) end group end |
#delete_key_pair(region, pair_name) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Deletes a given key pair
927 928 929 930 931 932 933 934 935 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 927 def delete_key_pair(region, pair_name) kp = client(region).describe_key_pairs(:key_names => [pair_name]).key_pairs.first unless kp.nil? @logger.debug("aws-sdk: delete key pair in region: #{region}") client(region).delete_key_pair(:key_name => pair_name) end rescue Aws::EC2::Errors::InvalidKeyPairNotFound nil end |
#delete_key_pair_all_regions(keypair_name_filter = nil) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Deletes key pairs from all regions
890 891 892 893 894 895 896 897 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 890 def delete_key_pair_all_regions(keypair_name_filter=nil) region_keypairs_hash = my_key_pairs(keypair_name_filter) region_keypairs_hash.each_pair do |region, keypair_name_array| keypair_name_array.each do |keypair_name| delete_key_pair(region, keypair_name) end end end |
#enable_root(host) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Enables root access for a host when username is not root
697 698 699 700 701 702 703 704 705 706 707 708 709 710 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 697 def enable_root(host) if host['user'] != 'root' if host['platform'] =~ /f5-/ enable_root_f5(host) elsif host['platform'] =~ /netscaler/ enable_root_netscaler(host) else copy_ssh_to_root(host, @options) enable_root_login(host, @options) host['user'] = 'root' end host.close end end |
#enable_root_f5(host) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method does not support other platforms
Enables root access for a host on an f5 platform
717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 717 def enable_root_f5(host) for tries in 1..10 begin #This command is problematic as the F5 is not always done loading if host.exec(Command.new("modify sys db systemauth.disablerootlogin value false"), :acceptable_exit_codes => [0,1]).exit_code == 0 \ and host.exec(Command.new("modify sys global-settings gui-setup disabled"), :acceptable_exit_codes => [0,1]).exit_code == 0 \ and host.exec(Command.new("save sys config"), :acceptable_exit_codes => [0,1]).exit_code == 0 backoff_sleep(tries) break elsif tries == 10 raise "Instance was unable to be configured" end rescue Beaker::Host::CommandFailure => e @logger.debug("Instance not yet configured (#{e})") end backoff_sleep(tries) end host['user'] = 'admin' sha256 = Digest::SHA256.new password = sha256.hexdigest((1..50).map{(rand(86)+40).chr}.join.gsub(/\\/,'\&\&')) + 'password!' # disabling password policy to account for the enforcement level set # and the generated password is sometimes too `01070366:3: Bad password (admin): BAD PASSWORD: \ # it is too simplistic/systematic` host.exec(Command.new('modify auth password-policy policy-enforcement disabled')) host.exec(Command.new("modify auth user admin password #{password}")) @logger.notify("f5: Configured admin password to be #{password}") host.close host['ssh'] = {:password => password} end |
#enable_root_netscaler(host) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method does not support other platforms
Enables root access for a host on an netscaler platform
752 753 754 755 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 752 def enable_root_netscaler(host) host['ssh'] = {:password => host['instance'].instance_id} @logger.notify("netscaler: nsroot password is #{host['instance'].instance_id}") end |
#enable_root_on_hosts ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Enables root for instances with custom username like ubuntu-amis
682 683 684 685 686 687 688 689 690 691 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 682 def enable_root_on_hosts @hosts.each do |host| if host['disable_root_ssh'] == true @logger.notify("aws-sdk: Not enabling root for instance as disable_root_ssh is set to 'true'.") else @logger.notify("aws-sdk: Enabling root ssh") enable_root(host) end end end |
#ensure_group(vpc, ports, sg_cidr_ips = ['0.0.0.0/0']) ⇒ Aws::EC2::SecurityGroup
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return an existing group, or create new one
Accepts a VPC as input for checking & creation.
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 1007 def ensure_group(vpc, ports, sg_cidr_ips = ['0.0.0.0/0']) @logger.notify("aws-sdk: Ensure security group exists for ports #{ports.to_s}, create if not") name = group_id(ports) group = client.describe_security_groups( :filters => [ { :name => 'group-name', :values => [name] }, { :name => 'vpc-id', :values => [vpc.vpc_id] }, ] ).security_groups.first if group.nil? group = create_group(vpc, ports, sg_cidr_ips) end group end |
#ensure_key_pair(region) ⇒ Aws::EC2::KeyPair
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Creates the KeyPair for this test run
876 877 878 879 880 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 876 def ensure_key_pair(region) pair_name = key_name() delete_key_pair(region, pair_name) create_new_key_pair(region, pair_name) end |
#ensure_ping_group(vpc, sg_cidr_ips = ['0.0.0.0/0']) ⇒ Aws::EC2::SecurityGroup
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return an existing group, or create new one
Accepts a VPC as input for checking & creation.
981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 981 def ensure_ping_group(vpc, sg_cidr_ips = ['0.0.0.0/0']) @logger.notify("aws-sdk: Ensure security group exists that enables ping, create if not") group = client.describe_security_groups( :filters => [ { :name => 'group-name', :values => [PING_SECURITY_GROUP_NAME] }, { :name => 'vpc-id', :values => [vpc.vpc_id] }, ] ).security_groups.first if group.nil? group = create_ping_group(vpc, sg_cidr_ips) end group end |
#etc_hosts_entry(host, interface = :ip) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return a valid /etc/hosts line for a given host
653 654 655 656 657 658 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 653 def etc_hosts_entry(host, interface = :ip) name = host.name domain = get_domain_name(host) ip = host[interface.to_s] "#{ip}\t#{name} #{name}.#{domain} #{host['dns_name']}\n" end |
#group_id(ports) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return a reproducable security group identifier based on input ports
960 961 962 963 964 965 966 967 968 969 970 971 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 960 def group_id(ports) if ports.nil? or ports.empty? raise ArgumentError, "Ports list cannot be nil or empty" end unless ports.is_a? Set ports = Set.new(ports) end # Lolwut, #hash is inconsistent between ruby processes "Beaker-#{Zlib.crc32(ports.inspect)}" end |
#instance_by_id(id) ⇒ Aws::EC2::Types::Instance
Provided an id return an instance object. Instance object will respond to methods described here: AWS Instance Object.
164 165 166 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 164 def instance_by_id(id) client.describe_instances(:instance_ids => [id]).reservations.first.instances.first end |
#instances ⇒ Array<Aws::Ec2::Types::Instance>
Return all instances currently on ec2.
171 172 173 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 171 def instances client.describe_instances.reservations.map(&:instances).flatten end |
#key_name ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Generate a reusable key name from the local hosts hostname
859 860 861 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 859 def key_name "#{key_name_prefix}-#{@options[:aws_keyname_modifier]}-#{@options[:timestamp].strftime("%F_%H_%M_%S_%N")}" end |
#key_name_prefix ⇒ String
This is the part of the key that will stay static between Beaker runs on the same host.
Generate a key prefix for key pair names
850 851 852 853 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 850 def key_name_prefix safe_hostname = Socket.gethostname.gsub('.', '-') "Beaker-#{local_user}-#{safe_hostname}" end |
#kill_instances(instances) ⇒ void
This method returns an undefined value.
Kill all instances.
106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 106 def kill_instances(instances) running_instances = instances.compact.select do |instance| instance_by_id(instance.instance_id).state.name == 'running' end instance_ids = running_instances.map(&:instance_id) return nil if instance_ids.empty? @logger.notify("aws-sdk: killing EC2 instance(s) #{instance_ids.join(', ')}") client.terminate_instances(:instance_ids => instance_ids) nil end |
#kill_zombie_volumes ⇒ Object
Destroy any volumes marked ‘available’, INCLUDING THOSE YOU DON’T OWN! Use with care.
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 241 def kill_zombie_volumes # Occasionaly, tearing down ec2 instances leaves orphaned EBS volumes behind -- these stack up quickly. # This simply looks for EBS volumes that are not in use @logger.notify("aws-sdk: Kill Zombie Volumes!") volume_count = 0 regions.each do |region| @logger.debug "Reviewing: #{region}" available_volumes = client(region).describe_volumes( :filters => [ { :name => 'status', :values => ['available'], } ] ).volumes available_volumes.each do |volume| begin client(region).delete_volume(:volume_id => volume.id) volume_count += 1 rescue Aws::EC2::Errors::InvalidVolume::NotFound => e @logger.debug "Failed to remove volume: #{volume.id} #{e}" end end end @logger.notify "Freed #{volume_count} volume(s)" end |
#kill_zombies(max_age = ZOMBIE, key = key_name) ⇒ Object
Shutdown and destroy ec2 instances idenfitied by key that have been alive longer than ZOMBIE hours.
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 210 def kill_zombies(max_age = ZOMBIE, key = key_name) @logger.notify("aws-sdk: Kill Zombies! (keyname: #{key}, age: #{max_age} hrs)") instances_to_kill = [] time_now = Time.now.getgm #ec2 uses GM time #examine all available regions regions.each do |region| @logger.debug "Reviewing: #{region}" client(region).describe_instances.reservations.each do |reservation| reservation.instances.each do |instance| if (instance.key_name =~ /#{key}/) @logger.debug "Examining #{instance.instance_id} (keyname: #{instance.key_name}, launch time: #{instance.launch_time}, state: #{instance.state.name})" if ((time_now - instance.launch_time) > max_age*60*60) and instance.state.name !~ /terminated/ @logger.debug "Kill! #{instance.instance_id}: #{instance.key_name} (Current status: #{instance.state.name})" instances_to_kill << instance end end end end end kill_instances(instances_to_kill) delete_key_pair_all_regions(key_name_prefix) @logger.notify "#{key}: Killed #{instances_to_kill.length} instance(s)" end |
#launch_all_nodes ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Create EC2 instances for all hosts, tag them, and wait until they’re running. When a host provides a subnet_id, create the instance in that subnet, otherwise prefer a CONFIG subnet_id. If neither are set but there is a CONFIG subnet_ids list, attempt to create the host in each specified subnet, which might fail due to capacity constraints, for example. Specifying both a CONFIG subnet_id and subnet_ids will provoke an error.
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 432 def launch_all_nodes @logger.notify("aws-sdk: launch all hosts in configuration") ami_spec = YAML.load_file(@options[:ec2_yaml])["AMI"] global_subnet_id = @options['subnet_id'] global_subnets = @options['subnet_ids'] if global_subnet_id and global_subnets raise RuntimeError, 'Config specifies both subnet_id and subnet_ids' end no_subnet_hosts = [] specific_subnet_hosts = [] some_subnet_hosts = [] @hosts.each do |host| if global_subnet_id or host['subnet_id'] specific_subnet_hosts.push(host) elsif global_subnets some_subnet_hosts.push(host) else no_subnet_hosts.push(host) end end instances = [] # Each element is {:instance => i, :host => h} begin @logger.notify("aws-sdk: launch instances not particular about subnet") launch_nodes_on_some_subnet(some_subnet_hosts, global_subnets, ami_spec, instances) @logger.notify("aws-sdk: launch instances requiring a specific subnet") specific_subnet_hosts.each do |host| subnet_id = host['subnet_id'] || global_subnet_id instance = create_instance(host, ami_spec, subnet_id) instances.push({:instance => instance, :host => host}) end @logger.notify("aws-sdk: launch instances requiring no subnet") no_subnet_hosts.each do |host| instance = create_instance(host, ami_spec, nil) instances.push({:instance => instance, :host => host}) end wait_for_status(:running, instances) rescue Exception => ex @logger.notify("aws-sdk: exception #{ex.class}: #{ex}") kill_instances(instances.map{|x| x[:instance]}) raise ex end # At this point, all instances should be running since wait # either returns on success or throws an exception. if instances.empty? raise RuntimeError, "Didn't manage to launch any EC2 instances" end # Assign the now known running instances to their hosts. instances.each {|x| x[:host]['instance'] = x[:instance]} nil end |
#launch_nodes_on_some_subnet(hosts, subnets, ami_spec, instances_created) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
For each host, create an EC2 instance in one of the specified subnets and push it onto instances_created. Each subnet will be tried at most once for each host, and more than one subnet may be tried if capacity constraints are encountered. Each Hash in instances_created will contain an :instance and :host value.
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 393 def launch_nodes_on_some_subnet(hosts, subnets, ami_spec, instances_created) # Shuffle the subnets so we don't always hit the same one # first, and cycle though the subnets independently of the # host, so we stick with one that's working. Try each subnet # once per-host. if subnets.nil? or subnets.empty? return end subnet_i = 0 shuffnets = subnets.shuffle hosts.each do |host| instance = nil shuffnets.length.times do begin subnet_id = shuffnets[subnet_i] instance = create_instance(host, ami_spec, subnet_id) instances_created.push({:instance => instance, :host => host}) break rescue Aws::EC2::Errors::InsufficientInstanceCapacity @logger.notify("aws-sdk: hit #{subnet_id} capacity limit; moving on") subnet_i = (subnet_i + 1) % shuffnets.length end end if instance.nil? raise RuntimeError, "unable to launch host in any requested subnet" end end end |
#load_credentials ⇒ Hash<Symbol, String>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return a hash containing AWS credentials
1119 1120 1121 1122 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 1119 def load_credentials return load_env_credentials if load_env_credentials.set? load_fog_credentials(@options[:dot_fog]) end |
#load_env_credentials(prefix = 'AWS') ⇒ Aws::Credentials
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return AWS credentials loaded from environment variables
1129 1130 1131 1132 1133 1134 1135 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 1129 def load_env_credentials(prefix='AWS') Aws::Credentials.new( ENV["#{prefix}_ACCESS_KEY_ID"], ENV["#{prefix}_SECRET_ACCESS_KEY"], ENV["#{prefix}_SESSION_TOKEN"] ) end |
#load_fog_credentials(dot_fog = '.fog') ⇒ Aws::Credentials
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return a hash containing the fog credentials for EC2
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 1142 def load_fog_credentials(dot_fog = '.fog') default = get_fog_credentials(dot_fog) raise "You must specify an aws_access_key_id in your .fog file (#{dot_fog}) for ec2 instances!" unless default[:aws_access_key_id] raise "You must specify an aws_secret_access_key in your .fog file (#{dot_fog}) for ec2 instances!" unless default[:aws_secret_access_key] Aws::Credentials.new( default[:aws_access_key_id], default[:aws_secret_access_key], default[:aws_session_token] ) end |
#local_user ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns the local user running this tool
867 868 869 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 867 def local_user ENV['USER'] end |
#log_instances(key = key_name, status = /running/) ⇒ Object
Print instances to the logger. Instances will be from all regions associated with provided key name and limited by regex compared to instance status. Defaults to running instances.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 139 def log_instances(key = key_name, status = /running/) instances = [] regions.each do |region| @logger.debug "Reviewing: #{region}" client(region).describe_instances.reservations.each do |reservation| reservation.instances.each do |instance| if (instance.key_name =~ /#{key}/) and (instance.state.name =~ status) instances << instance end end end end output = "" instances.each do |instance| dns_name = instance.public_dns_name || instance.private_dns_name output << "#{instance.instance_id} keyname: #{instance.key_name}, dns name: #{dns_name}, private ip: #{instance.private_ip_address}, ip: #{instance.public_ip_address}, launch time #{instance.launch_time}, status: #{instance.state.name}\n" end @logger.notify("aws-sdk: List instances (keyname: #{key})") @logger.notify("#{output}") end |
#modify_network_interface ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Add correct security groups to hosts network_interface as during the create_instance stage it is too early in process to configure
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 608 def modify_network_interface @hosts.each do |host| instance = host['instance'] host['sg_cidr_ips'] = host['sg_cidr_ips'] || '0.0.0.0/0'; sg_cidr_ips = host['sg_cidr_ips'].split(',') # Define tags for the instance @logger.notify("aws-sdk: Update network_interface for #{host.name}") security_group = ensure_group(instance[:network_interfaces].first, Beaker::EC2Helper.amiports(host), sg_cidr_ips) ping_security_group = ensure_ping_group(instance[:network_interfaces].first, sg_cidr_ips) client.modify_network_interface_attribute( :network_interface_id => "#{instance[:network_interfaces].first[:network_interface_id]}", :groups => [security_group.group_id, ping_security_group.group_id], ) end nil end |
#my_key_pairs(name_filter = nil) ⇒ Hash{String=>Array[String]}
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Gets the Beaker user’s keypairs by region
908 909 910 911 912 913 914 915 916 917 918 919 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 908 def my_key_pairs(name_filter=nil) keypairs_by_region = {} key_name_filter = name_filter ? "#{name_filter}-*" : key_name regions.each do |region| keypairs_by_region[region] = client(region).describe_key_pairs( :filters => [{ :name => 'key-name', :values => [key_name_filter] }] ).key_pairs.map(&:key_name) end keypairs_by_region end |
#populate_dns ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Populate the hosts IP address from the EC2 dns_name
633 634 635 636 637 638 639 640 641 642 643 644 645 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 633 def populate_dns # Obtain the IP addresses and dns_name for each host @hosts.each do |host| @logger.notify("aws-sdk: Populate DNS for #{host.name}") instance = host['instance'] host['ip'] = instance.public_ip_address || instance.private_ip_address host['private_ip'] = instance.private_ip_address host['dns_name'] = instance.public_dns_name || instance.private_dns_name @logger.notify("aws-sdk: name: #{host.name} ip: #{host['ip']} private_ip: #{host['private_ip']} dns_name: #{host['dns_name']}") end nil end |
#provision ⇒ void
This method returns an undefined value.
Provision all hosts on EC2 using the Aws::EC2 API
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 62 def provision start_time = Time.now # Perform the main launch work launch_all_nodes() # Add metadata tags to each instance # tagging early as some nodes take longer # to initialize and terminate before it has # a chance to provision () # adding the correct security groups to the # network interface, as during the `launch_all_nodes()` # step they never get assigned, although they get created modify_network_interface() wait_for_status_netdev() # Grab the ip addresses and dns from EC2 for each instance to use for ssh populate_dns() #enable root if user is not root enable_root_on_hosts() # Set the hostname for each box set_hostnames() # Configure /etc/hosts on each host configure_hosts() @logger.notify("aws-sdk: Provisioning complete in #{Time.now - start_time} seconds") nil #void end |
#public_key ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Retrieve the public key locally from the executing users ~/.ssh directory
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 827 def public_key keys = Array(@options[:ssh][:keys]) keys << '~/.ssh/id_rsa' keys << '~/.ssh/id_dsa' key_file = keys.find do |key| key_pub = key + '.pub' File.exist?(File.(key_pub)) && File.exist?(File.(key)) end if key_file @logger.debug("Using public key: #{key_file}") else raise RuntimeError, "Expected to find a public key, but couldn't in #{keys}" end File.read(File.(key_file + '.pub')) end |
#regions ⇒ Object
98 99 100 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 98 def regions @regions ||= client.describe_regions.regions.map(&:region_name) end |
#security_group_by_id(id) ⇒ Aws::EC2::Types::SecurityGroup
Provided an id return a security group object Security object will respond to methods described here: AWS SecurityGroup Object.
194 195 196 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 194 def security_group_by_id(id) client.describe_security_groups(:group_ids => [id]).security_groups.first end |
#security_groups ⇒ Array<Aws::EC2::Types::SecurityGroup>
Return all security groups currently on ec2.
201 202 203 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 201 def security_groups client.describe_security_groups.security_groups end |
#set_hostnames ⇒ @hosts
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Set the :vmhostname for each host object to be the dns_name, which is accessible publicly. Then configure each ec2 machine to that dns_name, so that when facter is installed the facts for hostname and domain match the dns_name.
if :use_beaker_hostnames: is true, set the :vmhostname and hostname of each ec2 machine to the host from the beaker hosts file.
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 766 def set_hostnames if @options[:use_beaker_hostnames] @hosts.each do |host| host[:vmhostname] = host.name if host['platform'] =~ /el-7/ # on el-7 hosts, the hostname command doesn't "stick" randomly host.exec(Command.new("hostnamectl set-hostname #{host.name}")) elsif host['platform'] =~ /windows/ @logger.notify('aws-sdk: Change hostname on windows is not supported.') else next if host['platform'] =~ /f5-|netscaler/ host.exec(Command.new("hostname #{host.name}")) if host['vmname'] =~ /^amazon/ # Amazon Linux requires this to preserve host name changes across reboots. # http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/set-hostname.html # Also note that without an elastic ip set, while this will # preserve the hostname across a full shutdown/startup of the vm # (as opposed to a reboot) -- the ip address will have changed. host.exec(Command.new("sed -ie '/^HOSTNAME/ s/=.*/=#{host.name}/' /etc/sysconfig/network")) end end end else @hosts.each do |host| host[:vmhostname] = host[:dns_name] if host['platform'] =~ /el-7/ # on el-7 hosts, the hostname command doesn't "stick" randomly host.exec(Command.new("hostnamectl set-hostname #{host.hostname}")) elsif host['platform'] =~ /windows/ @logger.notify('aws-sdk: Change hostname on windows is not supported.') else next if host['platform'] =~ /ft-|netscaler/ host.exec(Command.new("hostname #{host.hostname}")) if host['vmname'] =~ /^amazon/ # See note above host.exec(Command.new("sed -ie '/^HOSTNAME/ s/=.*/=#{host.hostname}/' /etc/sysconfig/network")) end end end end end |
#test_split_install ⇒ Object
Adds port 8143 to host if master, database and dashboard are not on same instance
1157 1158 1159 1160 1161 1162 1163 1164 1165 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 1157 def test_split_install @hosts.each do |host| mono_roles = ['master', 'database', 'dashboard'] roles_intersection = host[:roles] & mono_roles if roles_intersection.size != 3 && roles_intersection.any? host[:additional_ports] ? host[:additional_ports].push(8143) : host[:additional_ports] = [8143] end end end |
#vpc_by_id(id) ⇒ Aws::EC2::Types::Vpc
Provided an id return a VPC object. VPC object will respond to methods described here: AWS VPC Object.
179 180 181 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 179 def vpc_by_id(id) client.describe_vpcs(:vpc_ids => [id]).vpcs.first end |
#vpcs ⇒ Array<Aws::EC2::Types::Vpc>
Return all VPCs currently on ec2.
186 187 188 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 186 def vpcs client.describe_vpcs.vpcs end |
#wait_for_status(state_name, instances, &block) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Wait until all instances reach the desired state. Each Hash in instances must contain an :instance and :host value.
FIXME: rename to #wait_for_state
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 496 def wait_for_status(state_name, instances, &block) # Wait for each node to reach status :running @logger.notify("aws-sdk: Waiting for all hosts to be #{state_name}") instances.each do |x| name = x[:host] ? x[:host].name : x[:name] instance = x[:instance] @logger.notify("aws-sdk: Wait for node #{name} to be #{state_name}") # Here we keep waiting for the machine state to reach 'running' with an # exponential backoff for each poll. # TODO: should probably be a in a shared method somewhere for tries in 1..10 refreshed_instance = instance_by_id(instance.instance_id) if refreshed_instance.nil? @logger.debug("Instance #{name} not yet available (#{e})") else if block_given? test_result = yield refreshed_instance else test_result = refreshed_instance.state.name.to_s == state_name.to_s end if test_result x[:instance] = refreshed_instance # Always sleep, so the next command won't cause a throttle backoff_sleep(tries) break elsif tries == 10 raise "Instance never reached state #{state_name}" end end backoff_sleep(tries) end end end |
#wait_for_status_netdev ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
if any host is an netdev one, these checks will happen once across all of the hosts, and then we’ll exit
This method returns an undefined value.
Handles special checks needed for netdev platforms.
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 |
# File 'lib/beaker/hypervisor/aws_sdk.rb', line 539 def wait_for_status_netdev() @hosts.each do |host| if host['platform'] =~ /f5-|netscaler/ wait_for_status(:running, @hosts) wait_for_status(nil, @hosts) do |instance| instance_status_collection = client.describe_instance_status({:instance_ids => [instance.instance_id]}) first_instance = instance_status_collection.first[:instance_statuses].first first_instance[:instance_status][:status] == "ok" if first_instance end break end end end |