forked from vmoravec/cct
-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add VM scalling tests with cirros image;
Update and fix running openstack commands; Extend openstack commands by: * keypair * security_rule * security_group * ip_floating * flavor
- Loading branch information
Vladimir Moravec
committed
Feb 15, 2016
1 parent
8cc3402
commit ad7c0e2
Showing
16 changed files
with
554 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# You need to set the environment variable $cct_vm_number before running this feature | ||
# If your cloud doesn't have the same number of floating IPs as VMs available, set | ||
# the variable $cct_fip_number; floating IPs will be assigned to VMs picked randomly | ||
# from the created pool of VMs. Additionally you can set the way how the VMs are | ||
# going to be spawned, you either can rely on openstack managing the VMs' spawning | ||
# processt_vm_delay to delay the VMs' booting process by number of seconds. | ||
# | ||
# Configuration: | ||
# =================================================================================== | ||
# $cct_vm_number => number of VMs to spawn, mandatory | ||
# $cct_fip_number => number of floating IPs to be assigned to the created VMs, optional | ||
# $cct_wait_for_vm => optional, default is 1; | ||
# $cct_vm_reserve => optional, default is 3; increases the quotas due to VMs leftovers | ||
|
||
@scaling_vms | ||
Feature: Scaling VMs | ||
As a cloud administrator | ||
I want to verify the cloud can scale to VMs count defined by VM_COUNT env variable | ||
In order to make sure the cloud components work properly | ||
|
||
Background: | ||
Given the environment variable "cct_vm_number" is set | ||
And the variable "cct_vm_number" has value greater than zero | ||
And necessary rules for "default" security group on port "22" are present | ||
And necessary rules for "default" security group on "ipmc" protocol are present | ||
And "default" quotas for cores and instances in project "openstack" have been updated | ||
And respective quotas for nova in project "openstack" have been updated | ||
And respective quotas for neutron in project "openstack" have been updated | ||
|
||
@cirros | ||
Scenario: Scaling with cirros image | ||
Given the image named "cirros-.*x86_64.*-machine" is available | ||
And the flavor "cirros-test" is defined | ||
And the key pair "cirros-test" has been created | ||
And there are no VMs with the name "cirros-test-vm" present | ||
When I request creating VMs with name "cirros-test-vm" | ||
Then I get all the VMs listed as "ACTIVE" | ||
And there are enough floating IPs available | ||
And I assign floating IPs to the VMs | ||
And I can ping running VMs | ||
And I ssh to VMs successfully as "cirros" user | ||
And I remove the floating IPs from all VMs | ||
And I delete floating IPs from the pool | ||
And I delete all the VMs used for testing |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
Given(/^the environment variable "([^"]*)" is set$/) do |vm_count| | ||
expect(ENV[vm_count]).not_to be_nil | ||
end | ||
|
||
Given(/^the variable "([^"]*)" has value greater than zero$/) do |vm_count| | ||
@vm_count = ENV[vm_count].to_i | ||
expect(@vm_count).to be > 0 | ||
# Let's expect there is some number of VMs already in place (e.g. testsetup leftovers), | ||
# they must be considered when setting the quotas for neutron and nova later | ||
@vm_reserve = ENV["cct_vm_reserve"] || 3 | ||
end | ||
|
||
Given(/^necessary rules for "([^"]*)" security group on port "([^"]*)" are present$/) do |sec_group, port_number| | ||
rule_found = openstack.security_group.rule.list(sec_group).find do |rule| | ||
rule.port_range.match("#{port_number}:#{port_number}") | ||
end | ||
|
||
if !rule_found | ||
openstack.security_group.rule.create( | ||
sec_group, | ||
dst_port: port_number.to_i | ||
) | ||
end | ||
end | ||
|
||
Given(/^necessary rules for "([^"]*)" security group on "([^"]*)" protocol are present$/) do |sec_group, protocol| | ||
rule_found = openstack.security_group.rule.list(sec_group).find do |rule| | ||
rule.protocol == "icmp" | ||
end | ||
|
||
if !rule_found | ||
openstack.security_group.rule.create( | ||
sec_group, | ||
proto: "icmp" | ||
) | ||
end | ||
end | ||
|
||
Given(/^"([^"]*)" quotas for cores and instances in project "([^"]*)" have been updated$/) do |default, project| | ||
quota_class_update( | ||
"default", | ||
instances: @vm_count + @vm_reserve, | ||
cores: @vm_count + @vm_reserve, | ||
floating_ips: @vm_count + @vm_reserve | ||
) | ||
|
||
quota_class_update( | ||
project, | ||
instances: @vm_count + @vm_reserve, | ||
cores: @vm_count + @vm_reserve, | ||
floating_ips: @vm_count + @vm_reserve | ||
) | ||
end | ||
|
||
Given(/^respective quotas for nova in project "([^"]*)" have been updated$/) do |project| | ||
quota_update( | ||
:nova, | ||
floating_ips: @vm_count + @vm_reserve, | ||
instances: @vm_count + @vm_reserve, | ||
tenant: project | ||
) | ||
end | ||
|
||
Given(/^respective quotas for neutron in project "([^"]*)" have been updated$/) do |project| | ||
quota_update( | ||
:neutron, | ||
port: @vm_count + @vm_reserve, | ||
vip: @vm_count + @vm_reserve, | ||
tenant: project | ||
) | ||
|
||
quota_update( | ||
:neutron, | ||
port: @vm_count + @vm_reserve, | ||
vip: @vm_count + @vm_reserve, | ||
) | ||
end | ||
|
||
Given(/^the image named "([^"]*)" is available$/) do |image_name| | ||
image = openstack.image.list.find {|i| i.name.match(/#{image_name}$/) } | ||
@image = openstack.image.show(image.name) | ||
end | ||
|
||
Given(/^the flavor "([^"]*)" is defined$/) do |flavor| | ||
@flavor = openstack.flavor.list.find {|f| f.name == flavor } | ||
@flavor = openstack.flavor.create(flavor) if @flavor.nil? | ||
end | ||
|
||
Given(/^the key pair "([^"]*)" has been created$/) do |keypair_name| | ||
@key_path = "/tmp/#{keypair_name}" | ||
control_node.exec!("rm -rf #@key_path*") | ||
control_node.exec!( | ||
"ssh-keygen -t dsa -f #{@key_path} -N ''" | ||
) | ||
control_node.exec!( | ||
"chmod 600 #{@key_path}*" | ||
) | ||
|
||
if openstack.keypair.list.find {|k| k.name.match(keypair_name) } | ||
control_node.openstack.keypair.delete(keypair_name) | ||
end | ||
|
||
control_node.openstack.keypair.create(keypair_name, public_key: "#{@key_path}.pub") | ||
@keypair_name = keypair_name | ||
end | ||
|
||
Given(/^there are no VMs with the name "([^"]*)" present$/) do |vm_name| | ||
@vm_name = vm_name | ||
@wait = ENV["cct_wait_for_vm"].nil? ? true : (ENV["cct_wait_for_vm"].to_i.zero? ? false : true) | ||
delete_vms(name: @vm_name) | ||
end | ||
|
||
When(/^I request creating VMs with name "([^"]*)"$/) do |vm_name| | ||
|
||
options = { | ||
image: @image.name, | ||
flavor: @flavor.name, | ||
key_name: @keypair_name, | ||
} | ||
|
||
if @wait | ||
options.merge!(wait: true, max: @vm_count) | ||
openstack.server.create(vm_name, options) | ||
else | ||
1.upto(@vm_count).each do |num| | ||
openstack.server.create("#{vm_name}-#{num}", options) | ||
end | ||
end | ||
end | ||
|
||
Then(/^I get all the VMs listed as "([^"]*)"$/) do |status_active| | ||
@all_vms = [] | ||
wait_for("VMs being up and running successfully", max: "#{@vm_count*5} seconds", sleep: "2 seconds") do | ||
@all_vms = openstack.server.list.select {|vm| vm.name.match(@vm_name)} | ||
statuses = @all_vms.map(&:status) | ||
active = statuses.select {|status| status == "ACTIVE"} || [] | ||
break if active.count == @all_vms.count | ||
end | ||
expect(@all_vms.count).to eq(@vm_count) | ||
end | ||
|
||
Then(/^there are enough floating IPs available$/) do | ||
fip_limit = ENV["cct_fip_number"].to_i | ||
ips = openstack.ip_floating.list.select {|ip| ip.instance_id.empty? } | ||
|
||
if fip_limit.nonzero? | ||
needed = fip_limit > ips.size ? fip_limit - ips.size : fip_limit | ||
else | ||
needed = @all_vms.size - ips.size | ||
end | ||
|
||
1.upto(needed).each do | ||
openstack.ip_floating.create("floating") | ||
end | ||
@floating_ips = openstack.ip_floating.list.select {|ip| ip.instance_id.empty? } | ||
@all_vms = @all_vms.sample(fip_limit) if fip_limit.nonzero? | ||
end | ||
|
||
When(/^I assign floating IPs to the VMs$/) do | ||
Ip = Struct.new(:id, :ip) | ||
@vm_ips = {} | ||
@all_vms.each_with_index do |vm, index| | ||
floating = @floating_ips[index] | ||
openstack.ip_floating.add(floating.ip, vm.id) | ||
@vm_ips[vm.id] = Ip.new(floating.id, floating.ip) | ||
end | ||
end | ||
|
||
Then(/^I can ping running VMs$/) do | ||
@all_vms.each {|vm| ping_vm(@vm_ips[vm.id].ip) } | ||
end | ||
|
||
Then(/^I ssh to VMs successfully as "([^"]*)" user$/) do |user| | ||
@all_vms.each do |vm| | ||
control_node.exec!("ssh #{user}@#{@vm_ips[vm.id].ip} -i #{@key_path} 'echo test'") | ||
end | ||
end | ||
|
||
Then(/^I remove the floating IPs from all VMs$/) do | ||
@all_vms.each do |vm| | ||
openstack.ip_floating.remove(@vm_ips[vm.id].ip, vm.id) | ||
end | ||
end | ||
|
||
Then(/^I delete floating IPs from the pool$/) do | ||
@all_vms.each do |vm| | ||
openstack.ip_floating.delete(@vm_ips[vm.id].id) | ||
end | ||
end | ||
|
||
Then(/^I delete all the VMs used for testing$/) do | ||
delete_vms(name: @vm_name) | ||
end | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
module OpenstackHelpers | ||
|
||
def ping_vm ip | ||
control_node.exec!("ping", "-q -c 2 -w 3 #{ip}") | ||
end | ||
|
||
def delete_vms name: nil, wait: true, all: false, ids: [] | ||
options = wait ? {wait: true} : {} | ||
|
||
if !ids.empty? | ||
openstack.server.delete(ids, options) | ||
return | ||
end | ||
|
||
if all | ||
openstack.server.list.each {|s| openstack.server.delete(s.id, options) } | ||
return | ||
end | ||
|
||
vms = openstack.server.list | ||
ids = vms.select {|vm| vm.name.match(/#{name}/)}.map(&:id) | ||
openstack.server.delete(ids, options) unless ids.empty? | ||
end | ||
|
||
def openstack | ||
control_node.openstack | ||
end | ||
|
||
def quota_update component, options={} | ||
case component | ||
when :nova then nova_quota_update(options) | ||
when :neutron then neutron_quota_update(options) | ||
end | ||
end | ||
|
||
def quota_class_update classname, options | ||
command = "nova quota-class-update " | ||
command << "--instances #{options[:instances]} " if options[:instances] | ||
command << "--cores #{options[:cores]} " if options[:cores] | ||
command << "--floating #{options[:floating_ips]} " if options[:floating_ips] | ||
command << classname | ||
control_node.exec!(command) | ||
end | ||
|
||
private | ||
|
||
def nova_quota_update options | ||
command = "nova --insecure quota-update " | ||
command << "--floating-ips #{options[:floating_ips]} " | ||
command << "--instances #{options[:instances]} " | ||
command << options[:tenant] | ||
control_node.exec!(command) | ||
end | ||
|
||
def neutron_quota_update options | ||
command = "neutron --insecure quota-update " | ||
command << "--port #{options[:port]} " | ||
command << "--vip #{options[:vip]} " | ||
command << "--tenant-id #{options[:tenant]}" if options[:tenant] | ||
control_node.exec!(command) | ||
end | ||
|
||
end | ||
|
Oops, something went wrong.