Remove intree ec2-api tempest tests
ec2-api jobs have been switched to use ec2api-tempest-plugin for ec2-api tests, so we can remove the in-tree tempest tests now. Change-Id: I82ace9ebd1ca5216c2e3fc3d75f07146417ebf94
This commit is contained in:
parent
30ae9db6a1
commit
f5983d7cdc
|
@ -1,436 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
import botocore.exceptions
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class AddressTest(base.EC2TestCase):
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('218a4b6b-c3a9-44b0-8148-4bd0bc36bd7d')
|
||||
def test_create_delete_vpc_address(self):
|
||||
kwargs = {
|
||||
'Domain': 'vpc',
|
||||
}
|
||||
data = self.client.allocate_address(*[], **kwargs)
|
||||
id = data['AllocationId']
|
||||
res_clean = self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=id)
|
||||
self.assertEqual('vpc', data['Domain'])
|
||||
|
||||
data = self.client.release_address(AllocationId=id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@base.skip_without_ec2()
|
||||
@decorators.idempotent_id('285b8b4e-5aef-4e7f-be9e-37e6475be21b')
|
||||
def test_create_delete_standard_address(self):
|
||||
data = self.client.allocate_address()
|
||||
ip = data['PublicIp']
|
||||
res_clean = self.addResourceCleanUp(self.client.release_address,
|
||||
PublicIp=ip)
|
||||
|
||||
data = self.client.release_address(PublicIp=ip)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('5be3ad8d-b071-472b-b92a-7199c82334a2')
|
||||
def test_invalid_delete_vpc_address(self):
|
||||
kwargs = {
|
||||
'Domain': 'vpc',
|
||||
}
|
||||
data = self.client.allocate_address(*[], **kwargs)
|
||||
ip = data['PublicIp']
|
||||
id = data['AllocationId']
|
||||
res_clean = self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=id)
|
||||
self.assertEqual('vpc', data['Domain'])
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.release_address,
|
||||
PublicIp=ip, AllocationId=id)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.release_address,
|
||||
PublicIp=ip)
|
||||
|
||||
data = self.client.release_address(AllocationId=id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
self.assertRaises('AuthFailure',
|
||||
self.client.release_address,
|
||||
PublicIp=ip)
|
||||
|
||||
self.assertRaises('InvalidAllocationID.NotFound',
|
||||
self.client.release_address,
|
||||
AllocationId=id)
|
||||
|
||||
kwargs = {
|
||||
"AllocationId": 'eipalloc-00000000',
|
||||
}
|
||||
self.assertRaises('InvalidAllocationID.NotFound',
|
||||
self.client.release_address,
|
||||
**kwargs)
|
||||
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.release_address,
|
||||
PublicIp='ip')
|
||||
|
||||
@decorators.idempotent_id('e8171637-9ccd-471a-97da-c78a36ba3c4b')
|
||||
def test_invalid_create_address(self):
|
||||
kwargs = {
|
||||
'Domain': 'invalid',
|
||||
}
|
||||
try:
|
||||
data = self.client.allocate_address(*[], **kwargs)
|
||||
allocation_id = data.get('AllocationId')
|
||||
if allocation_id:
|
||||
self.client.release_address(AllocationId=allocation_id)
|
||||
else:
|
||||
public_ip = data.get('PublicIp')
|
||||
self.client.release_address(PublicIp=public_ip)
|
||||
except botocore.exceptions.ClientError as e:
|
||||
self.assertEqual('InvalidParameterValue',
|
||||
e.response['Error']['Code'])
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('b0d0b498-1fe2-479e-995c-80ace2f339a7')
|
||||
def test_describe_vpc_addresses(self):
|
||||
kwargs = {
|
||||
'Domain': 'vpc',
|
||||
}
|
||||
data = self.client.allocate_address(*[], **kwargs)
|
||||
ip = data['PublicIp']
|
||||
id = data['AllocationId']
|
||||
res_clean = self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=id)
|
||||
|
||||
data = self.client.describe_addresses(*[], **{})
|
||||
for address in data['Addresses']:
|
||||
if address.get('AllocationId') == id:
|
||||
self.assertEqual('vpc', address['Domain'])
|
||||
self.assertEqual(ip, address['PublicIp'])
|
||||
break
|
||||
else:
|
||||
self.fail('Created address could not be found')
|
||||
|
||||
kwargs = {
|
||||
'PublicIps': [ip],
|
||||
}
|
||||
data = self.client.describe_addresses(*[], **kwargs)
|
||||
self.assertEqual(1, len(data['Addresses']))
|
||||
self.assertEqual(id, data['Addresses'][0]['AllocationId'])
|
||||
|
||||
kwargs = {
|
||||
'AllocationIds': [id],
|
||||
}
|
||||
data = self.client.describe_addresses(*[], **kwargs)
|
||||
self.assertEqual(1, len(data['Addresses']))
|
||||
self.assertEqual(ip, data['Addresses'][0]['PublicIp'])
|
||||
|
||||
kwargs = {
|
||||
'PublicIps': ['invalidIp'],
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_addresses,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'AllocationIds': ['eipalloc-00000000'],
|
||||
}
|
||||
self.assertRaises('InvalidAllocationID.NotFound',
|
||||
self.client.describe_addresses,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'Domain': 'vpc',
|
||||
}
|
||||
data = self.client.allocate_address(*[], **kwargs)
|
||||
id2 = data['AllocationId']
|
||||
res_clean2 = self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=id2)
|
||||
|
||||
kwargs = {
|
||||
'PublicIps': [ip],
|
||||
'AllocationIds': [id2],
|
||||
}
|
||||
data = self.client.describe_addresses(*[], **kwargs)
|
||||
self.assertEqual(2, len(data['Addresses']))
|
||||
|
||||
# NOTE(andrey-mp): wait abit before releasing
|
||||
time.sleep(3)
|
||||
|
||||
self.client.release_address(AllocationId=id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
self.client.release_address(AllocationId=id2)
|
||||
self.cancelResourceCleanUp(res_clean2)
|
||||
|
||||
@base.skip_without_ec2()
|
||||
@decorators.idempotent_id('a5c09f47-3be3-4d46-b59d-25195d67e6d5')
|
||||
def test_describe_standard_addresses(self):
|
||||
data = self.client.allocate_address(*[], **{})
|
||||
ip = data['PublicIp']
|
||||
res_clean = self.addResourceCleanUp(self.client.release_address,
|
||||
PublicIp=ip)
|
||||
|
||||
data = self.client.describe_addresses(*[], **{})
|
||||
for address in data['Addresses']:
|
||||
if address['PublicIp'] == ip:
|
||||
self.assertEqual('standard', address['Domain'])
|
||||
break
|
||||
else:
|
||||
self.fail('Created address could not be found')
|
||||
|
||||
kwargs = {
|
||||
'PublicIps': [ip],
|
||||
}
|
||||
data = self.client.describe_addresses(*[], **kwargs)
|
||||
self.assertEqual(1, len(data['Addresses']))
|
||||
self.assertEqual(ip, data['Addresses'][0]['PublicIp'])
|
||||
|
||||
kwargs = {
|
||||
'PublicIps': ['invalidIp'],
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_addresses,
|
||||
PublicIps=['invalidIp'])
|
||||
|
||||
# NOTE(andrey-mp): wait abit before releasing
|
||||
time.sleep(3)
|
||||
|
||||
self.client.release_address(PublicIp=ip)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('6f154e48-f260-4d8d-b1d1-a1cf174f58fa')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_associate_disassociate_vpc_addresses(self):
|
||||
aws_zone = CONF.aws.aws_zone
|
||||
|
||||
base_net = '10.3.0.0'
|
||||
data = self.client.create_vpc(CidrBlock=base_net + '/20')
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
clean_vpc = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
cidr = base_net + '/24'
|
||||
data = self.client.create_subnet(VpcId=vpc_id, CidrBlock=cidr,
|
||||
AvailabilityZone=aws_zone)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
clean_subnet = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
|
||||
instance_id = self.run_instance(SubnetId=subnet_id)
|
||||
|
||||
data = self.client.allocate_address(Domain='vpc')
|
||||
alloc_id = data['AllocationId']
|
||||
clean_a = self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=alloc_id)
|
||||
|
||||
self.assertRaises('Gateway.NotAttached',
|
||||
self.client.associate_address,
|
||||
InstanceId=instance_id, AllocationId=alloc_id)
|
||||
|
||||
# Create internet gateway and try to associate again
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
clean_ig = self.addResourceCleanUp(self.client.delete_internet_gateway,
|
||||
InternetGatewayId=gw_id)
|
||||
data = self.client.attach_internet_gateway(VpcId=vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
clean_aig = self.addResourceCleanUp(
|
||||
self.client.detach_internet_gateway,
|
||||
VpcId=vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
self.prepare_route(vpc_id, gw_id)
|
||||
|
||||
data = self.client.associate_address(InstanceId=instance_id,
|
||||
AllocationId=alloc_id)
|
||||
assoc_id = data['AssociationId']
|
||||
clean_aa = self.addResourceCleanUp(self.client.disassociate_address,
|
||||
AssociationId=assoc_id)
|
||||
self.get_address_assoc_waiter().wait_available(
|
||||
{'AllocationId': alloc_id})
|
||||
|
||||
kwargs = {
|
||||
'AllocationIds': [alloc_id],
|
||||
}
|
||||
data = self.client.describe_addresses(*[], **kwargs)
|
||||
self.assertEqual(instance_id, data['Addresses'][0]['InstanceId'])
|
||||
|
||||
data = self.client.disassociate_address(AssociationId=assoc_id)
|
||||
self.cancelResourceCleanUp(clean_aa)
|
||||
self.get_address_assoc_waiter().wait_delete({'AllocationId': alloc_id})
|
||||
|
||||
# NOTE(andrey-mp): cleanup
|
||||
time.sleep(3)
|
||||
|
||||
self.client.detach_internet_gateway(VpcId=vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(clean_aig)
|
||||
|
||||
self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(clean_ig)
|
||||
|
||||
self.client.release_address(AllocationId=alloc_id)
|
||||
self.cancelResourceCleanUp(clean_a)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(clean_subnet)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(clean_vpc)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@decorators.idempotent_id('4aaf01d2-ade5-4e8b-b24a-ab22448b3236')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
# skip this test for nova network due to bug #1607350
|
||||
@base.skip_without_vpc()
|
||||
# this is a correct skip
|
||||
@base.skip_without_ec2()
|
||||
def test_associate_disassociate_standard_addresses(self):
|
||||
instance_id = self.run_instance()
|
||||
|
||||
data = self.client.allocate_address(*[], **{})
|
||||
ip = data['PublicIp']
|
||||
clean_a = self.addResourceCleanUp(self.client.release_address,
|
||||
PublicIp=ip)
|
||||
|
||||
data = self.client.associate_address(InstanceId=instance_id,
|
||||
PublicIp=ip)
|
||||
clean_aa = self.addResourceCleanUp(self.client.disassociate_address,
|
||||
PublicIp=ip)
|
||||
self.get_address_assoc_waiter().wait_available({'PublicIp': ip})
|
||||
|
||||
kwargs = {
|
||||
'PublicIps': [ip],
|
||||
}
|
||||
data = self.client.describe_addresses(*[], **kwargs)
|
||||
self.assertEqual(instance_id, data['Addresses'][0]['InstanceId'])
|
||||
|
||||
data = self.client.disassociate_address(PublicIp=ip)
|
||||
self.cancelResourceCleanUp(clean_aa)
|
||||
self.get_address_assoc_waiter().wait_delete({'PublicIp': ip})
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
data = self.client.release_address(PublicIp=ip)
|
||||
self.cancelResourceCleanUp(clean_a)
|
||||
|
||||
data = self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('3c0ab7f5-ee9c-4966-8d43-e89f5520f245')
|
||||
def test_disassociate_not_associated_vpc_addresses(self):
|
||||
aws_zone = CONF.aws.aws_zone
|
||||
|
||||
base_net = '10.3.0.0'
|
||||
data = self.client.create_vpc(CidrBlock=base_net + '/20')
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
clean_vpc = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
cidr = base_net + '/24'
|
||||
data = self.client.create_subnet(VpcId=vpc_id, CidrBlock=cidr,
|
||||
AvailabilityZone=aws_zone)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
clean_subnet = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
|
||||
data = self.client.allocate_address(Domain='vpc')
|
||||
alloc_id = data['AllocationId']
|
||||
ip = data['PublicIp']
|
||||
clean_a = self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=alloc_id)
|
||||
|
||||
assoc_id = 'eipassoc-00000001'
|
||||
self.assertRaises('InvalidAssociationID.NotFound',
|
||||
self.client.disassociate_address,
|
||||
AssociationId=assoc_id)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.disassociate_address,
|
||||
PublicIp=ip)
|
||||
|
||||
self.client.release_address(AllocationId=alloc_id)
|
||||
self.cancelResourceCleanUp(clean_a)
|
||||
|
||||
self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(clean_subnet)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(clean_vpc)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@base.skip_without_ec2()
|
||||
@decorators.idempotent_id('a70babef-18ec-4340-a3a2-63388cfc3cb5')
|
||||
def test_disassociate_not_associated_standard_addresses(self):
|
||||
data = self.client.allocate_address(Domain='standard')
|
||||
ip = data['PublicIp']
|
||||
clean_a = self.addResourceCleanUp(self.client.release_address,
|
||||
PublicIp=ip)
|
||||
|
||||
data = self.client.disassociate_address(PublicIp=ip)
|
||||
|
||||
data = self.client.release_address(PublicIp=ip)
|
||||
self.cancelResourceCleanUp(clean_a)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('91b971f5-2674-478e-84df-115fef506c5b')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
'preliminary address association is not supported')
|
||||
def test_preliminary_associate_address(self):
|
||||
# NOTE(ft): AWS can associate an address to a subnet IP if the subnet
|
||||
# has no internet access
|
||||
vpc_id, subnet_id = self.create_vpc_and_subnet('10.3.0.0/20')
|
||||
self.create_and_attach_internet_gateway(vpc_id)
|
||||
data = self.client.allocate_address(Domain='vpc')
|
||||
alloc_id = data['AllocationId']
|
||||
self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=alloc_id)
|
||||
|
||||
data = self.client.create_network_interface(SubnetId=subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
self.addResourceCleanUp(self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
data = self.client.associate_address(
|
||||
AllocationId=alloc_id, NetworkInterfaceId=ni_id)
|
||||
assoc_id = data['AssociationId']
|
||||
self.addResourceCleanUp(self.client.disassociate_address,
|
||||
AssociationId=assoc_id)
|
|
@ -1,57 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import botocore.exceptions
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class CustomerGatewayTest(base.EC2TestCase):
|
||||
|
||||
CUSTOMER_GATEWAY_IP = '198.51.100.77'
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(CustomerGatewayTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
base.check_network_feature_enabled('vpnaas')
|
||||
|
||||
@decorators.idempotent_id('54a40b66-1675-44b1-938d-0cad2eb6afe4')
|
||||
def test_create_delete_customer_gateway(self):
|
||||
data = self.client.create_customer_gateway(
|
||||
Type='ipsec.1', PublicIp=self.CUSTOMER_GATEWAY_IP, BgpAsn=65000)
|
||||
cgw_id = data['CustomerGateway']['CustomerGatewayId']
|
||||
cgw_clean = self.addResourceCleanUp(
|
||||
self.client.delete_customer_gateway, CustomerGatewayId=cgw_id)
|
||||
self.assertEqual(self.CUSTOMER_GATEWAY_IP,
|
||||
data['CustomerGateway']['IpAddress'])
|
||||
|
||||
self.client.delete_customer_gateway(CustomerGatewayId=cgw_id)
|
||||
self.cancelResourceCleanUp(cgw_clean)
|
||||
|
||||
try:
|
||||
data = self.client.describe_customer_gateways(
|
||||
CustomerGatewayIds=[cgw_id])
|
||||
self.assertEqual(1, len(data['CustomerGateways']))
|
||||
self.assertEqual('deleted', data['CustomerGateways'][0]['State'])
|
||||
except botocore.exceptions.ClientError as ex:
|
||||
self.assertEqual('InvalidCustomerGatewayID.NotFound',
|
||||
ex.response['Error']['Code'])
|
|
@ -1,182 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class DhcpOptionsTest(base.EC2TestCase):
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(DhcpOptionsTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
@decorators.idempotent_id('2331fc49-50e0-4df3-8c45-bd6f61cc86bf')
|
||||
def test_create_delete_dhcp_options(self):
|
||||
kwargs = {
|
||||
'DhcpConfigurations': [
|
||||
{'Key': 'domain-name',
|
||||
'Values': ['my.com', 'it.com']},
|
||||
{'Key': 'domain-name-servers',
|
||||
'Values': ['8.8.8.8', '8.8.4.4']},
|
||||
{'Key': 'ntp-servers',
|
||||
'Values': ['1.2.3.4']},
|
||||
{'Key': 'netbios-name-servers',
|
||||
'Values': ['4.3.2.1']},
|
||||
{'Key': 'netbios-node-type',
|
||||
'Values': ['2']},
|
||||
],
|
||||
}
|
||||
data = self.client.create_dhcp_options(*[], **kwargs)
|
||||
options = data['DhcpOptions']
|
||||
id = options['DhcpOptionsId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_dhcp_options,
|
||||
DhcpOptionsId=id)
|
||||
self.assertEqual(5, len(options['DhcpConfigurations']))
|
||||
for cfg in options['DhcpConfigurations']:
|
||||
self.assertEqual(2, len(cfg))
|
||||
if cfg['Key'] == 'domain-name':
|
||||
self.assertEqual(2, len(cfg['Values']))
|
||||
values = [i['Value'] for i in cfg['Values']]
|
||||
self.assertIn('my.com', values)
|
||||
self.assertIn('it.com', values)
|
||||
elif cfg['Key'] == 'domain-name-servers':
|
||||
self.assertEqual(2, len(cfg['Values']))
|
||||
values = [i['Value'] for i in cfg['Values']]
|
||||
self.assertIn('8.8.8.8', values)
|
||||
self.assertIn('8.8.4.4', values)
|
||||
elif cfg['Key'] == 'ntp-servers':
|
||||
self.assertEqual(1, len(cfg['Values']))
|
||||
self.assertEqual('1.2.3.4', cfg['Values'][0]['Value'])
|
||||
elif cfg['Key'] == 'netbios-name-servers':
|
||||
self.assertEqual(1, len(cfg['Values']))
|
||||
self.assertEqual('4.3.2.1', cfg['Values'][0]['Value'])
|
||||
elif cfg['Key'] == 'netbios-node-type':
|
||||
self.assertEqual(1, len(cfg['Values']))
|
||||
self.assertEqual('2', cfg['Values'][0]['Value'])
|
||||
else:
|
||||
self.fail('Unknown key name in result - %s' % cfg['Key'])
|
||||
|
||||
data = self.client.delete_dhcp_options(DhcpOptionsId=id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('ff1d4f6e-97fc-4053-b98f-ff59e7e8d061')
|
||||
def test_invalid_create_delete(self):
|
||||
def _rollback(fn_data):
|
||||
self.client.delete_dhcp_options(
|
||||
DhcpOptionsId=fn_data['DhcpOptions']['DhcpOptionsId'])
|
||||
|
||||
kwargs = {
|
||||
'DhcpConfigurations': [
|
||||
],
|
||||
}
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.create_dhcp_options,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DhcpConfigurations': [{'Key': 'aaa', 'Values': []}],
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.create_dhcp_options, rollback_fn=_rollback,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DhcpConfigurations': [{'Key': 'domain-name', 'Values': []}],
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.create_dhcp_options, rollback_fn=_rollback,
|
||||
**kwargs)
|
||||
|
||||
@decorators.idempotent_id('1c3e8ff9-bb3b-40ba-889e-d2306a92f418')
|
||||
def test_describe_dhcp_options(self):
|
||||
kwargs = {
|
||||
'DhcpConfigurations': [
|
||||
{'Key': 'domain-name',
|
||||
'Values': ['my.com']},
|
||||
],
|
||||
}
|
||||
data = self.client.create_dhcp_options(*[], **kwargs)
|
||||
options = data['DhcpOptions']
|
||||
id = options['DhcpOptionsId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_dhcp_options,
|
||||
DhcpOptionsId=id)
|
||||
|
||||
time.sleep(10)
|
||||
|
||||
kwargs = {
|
||||
'DhcpOptionsIds': [id],
|
||||
}
|
||||
data = self.client.describe_dhcp_options(*[], **kwargs)
|
||||
self.assertEqual(1, len(data['DhcpOptions']))
|
||||
options = data['DhcpOptions'][0]
|
||||
self.assertEqual(id, options['DhcpOptionsId'])
|
||||
self.assertEqual(1, len(options['DhcpConfigurations']))
|
||||
cfg = options['DhcpConfigurations'][0]
|
||||
self.assertEqual(2, len(cfg))
|
||||
self.assertEqual('domain-name', cfg['Key'])
|
||||
self.assertEqual(1, len(cfg['Values']))
|
||||
self.assertIn('my.com', cfg['Values'][0]['Value'])
|
||||
|
||||
data = self.client.delete_dhcp_options(DhcpOptionsId=id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('1b4d678a-c2a2-4c73-9e62-789fe2f6b173')
|
||||
def test_associate_dhcp_options(self):
|
||||
kwargs = {
|
||||
'DhcpConfigurations': [
|
||||
{'Key': 'domain-name',
|
||||
'Values': ['my.com']},
|
||||
],
|
||||
}
|
||||
data = self.client.create_dhcp_options(*[], **kwargs)
|
||||
options = data['DhcpOptions']
|
||||
id = options['DhcpOptionsId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_dhcp_options,
|
||||
DhcpOptionsId=id)
|
||||
|
||||
cidr = '10.0.0.0/24'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
|
||||
kwargs = {
|
||||
'DhcpOptionsId': id,
|
||||
'VpcId': vpc_id,
|
||||
}
|
||||
data = self.client.associate_dhcp_options(*[], **kwargs)
|
||||
|
||||
self.assertRaises('DependencyViolation',
|
||||
self.client.delete_dhcp_options,
|
||||
DhcpOptionsId=id)
|
||||
|
||||
data = self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
data = self.client.delete_dhcp_options(DhcpOptionsId=id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
|
@ -1,359 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class ImageTest(base.EC2TestCase):
|
||||
|
||||
@decorators.idempotent_id('19a2fda6-0b78-4544-a6c5-ac16f39811c8')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_check_ebs_image_type(self):
|
||||
image_id = CONF.aws.ebs_image_id
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
self.assertEqual(1, len(data['Images']))
|
||||
image = data['Images'][0]
|
||||
self.assertEqual("ebs", image['RootDeviceType'],
|
||||
"Image is not EBS image")
|
||||
|
||||
@decorators.idempotent_id('d45be578-5968-4189-8f25-56bf8ef23d20')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_check_ebs_image_volume_properties(self):
|
||||
image_id = CONF.aws.ebs_image_id
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
self.assertEqual(1, len(data['Images']))
|
||||
image = data['Images'][0]
|
||||
self.assertTrue(image['RootDeviceName'])
|
||||
self.assertTrue(image['BlockDeviceMappings'])
|
||||
device_name = image['RootDeviceName']
|
||||
bdm = image['BlockDeviceMappings']
|
||||
bdm = [v for v in bdm if v['DeviceName'] == device_name]
|
||||
self.assertEqual(1, len(bdm))
|
||||
bdm = bdm[0]
|
||||
self.assertIn('Ebs', bdm)
|
||||
ebs = bdm['Ebs']
|
||||
self.assertIsNotNone(ebs.get('SnapshotId'))
|
||||
self.assertIsNotNone(ebs.get('DeleteOnTermination'))
|
||||
self.assertIsNotNone(ebs.get('VolumeSize'))
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
self.assertIsNotNone(ebs.get('Encrypted'))
|
||||
self.assertFalse(ebs.get('Encrypted'))
|
||||
self.assertIsNotNone(ebs.get('VolumeType'))
|
||||
|
||||
@decorators.idempotent_id('a139f5ea-45fd-4b3e-9a52-32de0f8c3bca')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_describe_image_with_filters(self):
|
||||
image_id = CONF.aws.ebs_image_id
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
self.assertEqual(1, len(data['Images']))
|
||||
|
||||
data = self.client.describe_images(
|
||||
# NOTE(ft): limit output to prevent timeout over AWS
|
||||
Filters=[{'Name': 'image-type', 'Values': ['kernel', 'ramdisk']}])
|
||||
if len(data['Images']) < 2:
|
||||
self.skipTest("Insufficient images to check filters")
|
||||
data = self.client.describe_images(
|
||||
Filters=[{'Name': 'image-id', 'Values': [image_id]}])
|
||||
self.assertEqual(1, len(data['Images']))
|
||||
self.assertEqual(image_id, data['Images'][0]['ImageId'])
|
||||
|
||||
@decorators.idempotent_id('743e1f87-e0b6-4787-ab22-176379030007')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "Image id is not defined")
|
||||
def test_check_image_operations_negative(self):
|
||||
# NOTE(andrey-mp): image_id is a public image created by admin
|
||||
image_id = CONF.aws.image_id
|
||||
|
||||
self.assertRaises('InvalidRequest',
|
||||
self.client.describe_image_attribute,
|
||||
ImageId=image_id, Attribute='unsupported')
|
||||
|
||||
self.assertRaises('AuthFailure',
|
||||
self.client.describe_image_attribute,
|
||||
ImageId=image_id, Attribute='description')
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_image_attribute,
|
||||
ImageId=image_id, Attribute='unsupported')
|
||||
|
||||
self.assertRaises('InvalidParameter',
|
||||
self.client.modify_image_attribute,
|
||||
ImageId=image_id, Attribute='blockDeviceMapping')
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_image_attribute,
|
||||
ImageId=image_id)
|
||||
|
||||
self.assertRaises('AuthFailure',
|
||||
self.client.modify_image_attribute,
|
||||
ImageId=image_id, Description={'Value': 'fake'})
|
||||
|
||||
self.assertRaises('AuthFailure',
|
||||
self.client.modify_image_attribute,
|
||||
ImageId=image_id, LaunchPermission={'Add': [{'Group': 'all'}]})
|
||||
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.modify_image_attribute,
|
||||
ImageId=image_id, Attribute='description')
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_image_attribute,
|
||||
ImageId=image_id, Attribute='launchPermission')
|
||||
|
||||
self.assertRaises('InvalidRequest',
|
||||
self.client.reset_image_attribute,
|
||||
ImageId=image_id, Attribute='fake')
|
||||
|
||||
self.assertRaises('AuthFailure',
|
||||
self.client.reset_image_attribute,
|
||||
ImageId=image_id, Attribute='launchPermission')
|
||||
|
||||
self.assertRaises('AuthFailure',
|
||||
self.client.deregister_image,
|
||||
ImageId=image_id)
|
||||
|
||||
@decorators.idempotent_id('a948dad1-9128-446b-86ee-82db13342054')
|
||||
@testtools.skipUnless(CONF.aws.image_id, 'image id is not defined')
|
||||
def test_create_image_from_non_ebs_instance(self):
|
||||
image_id = CONF.aws.image_id
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
image = data['Images'][0]
|
||||
if 'RootDeviceType' in image and 'ebs' in image['RootDeviceType']:
|
||||
raise self.skipException('image_id should not be EBS image.')
|
||||
|
||||
instance_id = self.run_instance(ImageId=image_id)
|
||||
|
||||
def _rollback(fn_data):
|
||||
self.client.deregister_image(ImageId=fn_data['ImageId'])
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.create_image, rollback_fn=_rollback,
|
||||
InstanceId=instance_id, Name='name', Description='desc')
|
||||
|
||||
data = self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
def _create_image(self, name, desc, extra_run_instance_args={}):
|
||||
image_id = CONF.aws.ebs_image_id
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
image = data['Images'][0]
|
||||
self.assertTrue('RootDeviceType' in image
|
||||
and 'ebs' in image['RootDeviceType'])
|
||||
|
||||
instance_id = self.run_instance(ImageId=image_id,
|
||||
**extra_run_instance_args)
|
||||
instance = self.get_instance(instance_id)
|
||||
for bdm in instance.get('BlockDeviceMappings', []):
|
||||
if 'Ebs' in bdm:
|
||||
self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=bdm['Ebs']['VolumeId'])
|
||||
|
||||
data = self.client.create_image(InstanceId=instance_id,
|
||||
Name=name, Description=desc)
|
||||
image_id = data['ImageId']
|
||||
image_clean = self.addResourceCleanUp(self.client.deregister_image,
|
||||
ImageId=image_id)
|
||||
self.get_image_waiter().wait_available(image_id)
|
||||
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
for bdm in data['Images'][0].get('BlockDeviceMappings', []):
|
||||
if 'Ebs' in bdm and 'SnapshotId' in bdm['Ebs']:
|
||||
snapshot_id = bdm['Ebs']['SnapshotId']
|
||||
self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
|
||||
data = self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
return image_id, image_clean
|
||||
|
||||
@decorators.idempotent_id('f4fbb311-8a59-443d-a60a-11779917c757')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_create_image_from_ebs_instance(self):
|
||||
name = data_utils.rand_name('image')
|
||||
desc = data_utils.rand_name('description')
|
||||
image_id, image_clean = self._create_image(name, desc)
|
||||
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
self.assertEqual(1, len(data['Images']))
|
||||
image = data['Images'][0]
|
||||
|
||||
self.assertIsNotNone(image['CreationDate'])
|
||||
self.assertEqual("ebs", image['RootDeviceType'])
|
||||
self.assertFalse(image['Public'])
|
||||
self.assertEqual(name, image['Name'])
|
||||
self.assertEqual(desc, image['Description'])
|
||||
self.assertEqual('machine', image['ImageType'])
|
||||
self.assertNotEmpty(image['BlockDeviceMappings'])
|
||||
for bdm in image['BlockDeviceMappings']:
|
||||
self.assertIn('DeviceName', bdm)
|
||||
|
||||
data = self.client.deregister_image(ImageId=image_id)
|
||||
self.cancelResourceCleanUp(image_clean)
|
||||
|
||||
@decorators.idempotent_id('b9aba1f7-0a7e-4717-b879-efe3bbea74e2')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_check_simple_image_attributes(self):
|
||||
data = self.client.describe_images(ImageIds=[CONF.aws.ebs_image_id])
|
||||
base_image = data['Images'][0]
|
||||
|
||||
name = data_utils.rand_name('image')
|
||||
desc = data_utils.rand_name('desc for image')
|
||||
image_id, image_clean = self._create_image(name, desc)
|
||||
|
||||
data = self.client.describe_image_attribute(
|
||||
ImageId=image_id, Attribute='kernel')
|
||||
if 'KernelId' in base_image:
|
||||
self.assertIn('KernelId', data)
|
||||
else:
|
||||
self.assertNotIn('KernelId', data)
|
||||
|
||||
data = self.client.describe_image_attribute(
|
||||
ImageId=image_id, Attribute='ramdisk')
|
||||
if 'RamdiskId' in base_image:
|
||||
self.assertIn('RamdiskId', data)
|
||||
else:
|
||||
self.assertNotIn('RamdiskId', data)
|
||||
|
||||
# description
|
||||
data = self.client.describe_image_attribute(
|
||||
ImageId=image_id, Attribute='description')
|
||||
self.assertIn('Description', data)
|
||||
self.assertIn('Value', data['Description'])
|
||||
self.assertEqual(desc, data['Description']['Value'])
|
||||
|
||||
def _modify_description(**kwargs):
|
||||
self.client.modify_image_attribute(ImageId=image_id, **kwargs)
|
||||
data = self.client.describe_image_attribute(
|
||||
ImageId=image_id, Attribute='description')
|
||||
self.assertEqual(new_desc, data['Description']['Value'])
|
||||
|
||||
new_desc = data_utils.rand_name('new desc')
|
||||
_modify_description(Attribute='description', Value=new_desc)
|
||||
_modify_description(Description={'Value': new_desc})
|
||||
|
||||
data = self.client.deregister_image(ImageId=image_id)
|
||||
self.cancelResourceCleanUp(image_clean)
|
||||
|
||||
@decorators.idempotent_id('680963cf-84f2-488d-bcdb-fc6f9b39f78c')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_check_bdm_in_image(self):
|
||||
image_id = CONF.aws.ebs_image_id
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
root_device_name = data['Images'][0]['RootDeviceName']
|
||||
device_name_prefix = base.get_device_name_prefix(root_device_name)
|
||||
device_name = device_name_prefix + 'h'
|
||||
|
||||
name = data_utils.rand_name('image')
|
||||
desc = data_utils.rand_name('description')
|
||||
image_id, image_clean = self._create_image(
|
||||
name, desc,
|
||||
extra_run_instance_args={
|
||||
'BlockDeviceMappings': [{'DeviceName': device_name,
|
||||
'Ebs': {'VolumeSize': 1}}]})
|
||||
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
image = data['Images'][0]
|
||||
|
||||
for bdm in image['BlockDeviceMappings']:
|
||||
self.assertTrue('DeviceName', bdm)
|
||||
|
||||
data = self.client.deregister_image(ImageId=image_id)
|
||||
self.cancelResourceCleanUp(image_clean)
|
||||
|
||||
@decorators.idempotent_id('1c244c9a-af3e-47f0-bc85-034e24b051e4')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
'By default glance is configured as "publicize_image": "role:admin"')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
'skip due to bug #1439819')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_check_launch_permission_attribute(self):
|
||||
name = data_utils.rand_name('image')
|
||||
desc = data_utils.rand_name('desc for image')
|
||||
image_id, image_clean = self._create_image(name, desc)
|
||||
|
||||
# launch permission
|
||||
data = self.client.describe_image_attribute(
|
||||
ImageId=image_id, Attribute='launchPermission')
|
||||
self.assertIn('LaunchPermissions', data)
|
||||
self.assertEmpty(data['LaunchPermissions'])
|
||||
|
||||
def _modify_launch_permission(**kwargs):
|
||||
self.client.modify_image_attribute(ImageId=image_id, **kwargs)
|
||||
data = self.client.describe_image_attribute(
|
||||
ImageId=image_id, Attribute='launchPermission')
|
||||
self.assertIn('LaunchPermissions', data)
|
||||
self.assertNotEmpty(data['LaunchPermissions'])
|
||||
self.assertIn('Group', data['LaunchPermissions'][0])
|
||||
self.assertEqual('all', data['LaunchPermissions'][0]['Group'])
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
self.assertTrue(data['Images'][0]['Public'])
|
||||
|
||||
self.client.reset_image_attribute(
|
||||
ImageId=image_id, Attribute='launchPermission')
|
||||
data = self.client.describe_image_attribute(
|
||||
ImageId=image_id, Attribute='launchPermission')
|
||||
self.assertEmpty(data['LaunchPermissions'])
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
self.assertFalse(data['Images'][0]['Public'])
|
||||
|
||||
_modify_launch_permission(Attribute='launchPermission',
|
||||
OperationType='add', UserGroups=['all'])
|
||||
_modify_launch_permission(LaunchPermission={'Add': [{'Group': 'all'}]})
|
||||
|
||||
data = self.client.deregister_image(ImageId=image_id)
|
||||
self.cancelResourceCleanUp(image_clean)
|
||||
|
||||
|
||||
class ImageRegisterTest(base.EC2TestCase):
|
||||
|
||||
valid_image_state = set(('available', 'pending', 'failed'))
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(ImageRegisterTest, cls).setUpClass()
|
||||
cls.image_location = CONF.aws.ami_image_location
|
||||
if not cls.image_location:
|
||||
raise cls.skipException('Image materials are not ready in S3')
|
||||
|
||||
@decorators.idempotent_id('3e25269d-c8a2-4438-ab25-c343cb53db79')
|
||||
def test_register_get_deregister_ami_image(self):
|
||||
image_name = data_utils.rand_name("ami-name")
|
||||
data = self.client.register_image(
|
||||
Name=image_name, ImageLocation=self.image_location)
|
||||
image_id = data['ImageId']
|
||||
image_clean = self.addResourceCleanUp(self.client.deregister_image,
|
||||
ImageId=image_id)
|
||||
self.assertEqual(image_id[0:3], "ami")
|
||||
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
self.assertEqual(1, len(data['Images']))
|
||||
image = data['Images'][0]
|
||||
self.assertEqual(image_name, image['Name'])
|
||||
self.assertEqual(image_id, image['ImageId'])
|
||||
self.assertIn(image['State'], self.valid_image_state)
|
||||
|
||||
self.get_image_waiter().wait_available(image_id)
|
||||
|
||||
self.client.deregister_image(ImageId=image_id)
|
||||
self.cancelResourceCleanUp(image_clean)
|
||||
self.get_image_waiter().wait_delete(image_id)
|
|
@ -1,365 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class InstanceAttributeTest(base.EC2TestCase):
|
||||
|
||||
@decorators.idempotent_id('485107d8-f65f-4441-9558-2ff783e52e22')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_describe_instance_attributes(self):
|
||||
instance_id = self.run_instance(ImageId=CONF.aws.ebs_image_id)
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='blockDeviceMapping')
|
||||
bdms = data.get('BlockDeviceMappings', [])
|
||||
self.assertNotEmpty(bdms)
|
||||
self.assertEqual(1, len(bdms))
|
||||
self.assertIn('DeviceName', bdms[0])
|
||||
self.assertIn('Ebs', bdms[0])
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='disableApiTermination')
|
||||
self.assertIn('DisableApiTermination', data)
|
||||
self.assertIn('Value', data['DisableApiTermination'])
|
||||
self.assertFalse(data['DisableApiTermination']['Value'])
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='groupSet')
|
||||
self.assertIn('Groups', data)
|
||||
self.assertNotEmpty(data['Groups'], data)
|
||||
self.assertTrue('GroupId' in data['Groups'][0]
|
||||
or 'GroupName' in data['Groups'][0])
|
||||
self.assertTrue(data['Groups'][0].get('GroupId')
|
||||
or data['Groups'][0].get('GroupName'))
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='instanceType')
|
||||
self.assertIn('InstanceType', data)
|
||||
self.assertIn('Value', data['InstanceType'])
|
||||
self.assertEqual(CONF.aws.instance_type, data['InstanceType']['Value'])
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='kernel')
|
||||
self.assertIn('KernelId', data)
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='ramdisk')
|
||||
self.assertIn('RamdiskId', data)
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='rootDeviceName')
|
||||
self.assertIn('RootDeviceName', data)
|
||||
self.assertIn('Value', data['RootDeviceName'])
|
||||
self.assertTrue(data['RootDeviceName']['Value'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('391f6645-d014-42c7-a727-f3a6e7a13a4c')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_disable_api_termination_attribute(self):
|
||||
instance_id = self.run_instance(DisableApiTermination=True)
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id,
|
||||
DisableApiTermination={'Value': False})
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='disableApiTermination')
|
||||
self.assertIn('DisableApiTermination', data)
|
||||
self.assertIn('Value', data['DisableApiTermination'])
|
||||
self.assertTrue(data['DisableApiTermination']['Value'])
|
||||
|
||||
data = self.client.modify_instance_attribute(InstanceId=instance_id,
|
||||
Attribute='disableApiTermination', Value='False')
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='disableApiTermination')
|
||||
self.assertFalse(data['DisableApiTermination']['Value'])
|
||||
|
||||
data = self.client.modify_instance_attribute(InstanceId=instance_id,
|
||||
Attribute='disableApiTermination', Value='True')
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='disableApiTermination')
|
||||
self.assertTrue(data['DisableApiTermination']['Value'])
|
||||
|
||||
self.assertRaises('OperationNotPermitted',
|
||||
self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
|
||||
data = self.client.modify_instance_attribute(InstanceId=instance_id,
|
||||
DisableApiTermination={'Value': False})
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='disableApiTermination')
|
||||
self.assertFalse(data['DisableApiTermination']['Value'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('50671a21-99bf-4514-acb0-97617f92e868')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_instance_attributes_negative(self):
|
||||
instance_id = self.run_instance()
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='fake_attribute')
|
||||
self.assertRaises('InvalidInstanceID.NotFound',
|
||||
self.client.describe_instance_attribute,
|
||||
InstanceId='i-0', Attribute='disableApiTermination')
|
||||
if base.TesterStateHolder().get_ec2_enabled():
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.describe_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck')
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='fake_attribute')
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='disableApiTermination')
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id)
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='disableApiTermination',
|
||||
Value='True', DisableApiTermination={'Value': False})
|
||||
|
||||
ex_str = ('InvalidParameterCombination'
|
||||
if base.TesterStateHolder().get_ec2_enabled() else
|
||||
'InvalidGroup.NotFound')
|
||||
self.assertRaises(ex_str,
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, Groups=['sg-0'])
|
||||
if base.TesterStateHolder().get_ec2_enabled():
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck',
|
||||
Value='False')
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.reset_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='fake_attribute')
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.reset_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='disableApiTermination')
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.reset_instance_attribute,
|
||||
InstanceId='i-0', Attribute='disableApiTermination')
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.reset_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='groupSet')
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.reset_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='instanceType')
|
||||
|
||||
if base.TesterStateHolder().get_ec2_enabled():
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.reset_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck')
|
||||
|
||||
self.assertRaises('IncorrectInstanceState',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='instanceType',
|
||||
Value=CONF.aws.instance_type)
|
||||
self.assertRaises('IncorrectInstanceState',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id,
|
||||
InstanceType={'Value': CONF.aws.instance_type})
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('6fd2c8eb-f7f9-420d-a8ae-5d5af3a49a35')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_attributes_for_multiple_interfaces_negative(self):
|
||||
vpc_id, subnet_id = self.create_vpc_and_subnet('10.30.0.0/24')
|
||||
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(VpcId=vpc_id, GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
data = self.client.create_network_interface(SubnetId=subnet_id,
|
||||
Groups=[group_id])
|
||||
ni_id2 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
self.addResourceCleanUp(self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id2)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
|
||||
instance_id = self.run_instance(SubnetId=subnet_id)
|
||||
|
||||
kwargs = {
|
||||
'DeviceIndex': 2,
|
||||
'InstanceId': instance_id,
|
||||
'NetworkInterfaceId': ni_id2
|
||||
}
|
||||
data = self.client.attach_network_interface(*[], **kwargs)
|
||||
|
||||
self.assertRaises('InvalidInstanceID',
|
||||
self.client.describe_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='groupSet')
|
||||
self.assertRaises('InvalidInstanceID',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, Groups=['sg-0'])
|
||||
|
||||
self.assertRaises('InvalidInstanceID',
|
||||
self.client.describe_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck')
|
||||
self.assertRaises('InvalidInstanceID',
|
||||
self.client.modify_instance_attribute,
|
||||
InstanceId=instance_id, SourceDestCheck={'Value': False})
|
||||
self.assertRaises('InvalidInstanceID',
|
||||
self.client.reset_instance_attribute,
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck')
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('da26cc0d-6c2d-4638-97f1-1abfae8f00b5')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_group_set_attribute(self):
|
||||
vpc_id, subnet_id = self.create_vpc_and_subnet('10.30.0.0/24')
|
||||
|
||||
instance_id = self.run_instance(SubnetId=subnet_id)
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='groupSet')
|
||||
self.assertIn('Groups', data)
|
||||
self.assertEqual(1, len(data['Groups']))
|
||||
default_group_id = data['Groups'][0]['GroupId']
|
||||
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(VpcId=vpc_id, GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
|
||||
try:
|
||||
data = self.client.modify_instance_attribute(
|
||||
InstanceId=instance_id, Groups=[group_id])
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='groupSet')
|
||||
self.assertIn('Groups', data)
|
||||
self.assertEqual(1, len(data['Groups']))
|
||||
self.assertNotEqual(default_group_id, data['Groups'][0]['GroupId'])
|
||||
|
||||
self.assertRaises('DependencyViolation',
|
||||
self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
finally:
|
||||
self.client.modify_instance_attribute(InstanceId=instance_id,
|
||||
Groups=[default_group_id])
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='groupSet')
|
||||
self.assertIn('Groups', data)
|
||||
self.assertEqual(1, len(data['Groups']))
|
||||
self.assertEqual(default_group_id, data['Groups'][0]['GroupId'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('8e7b37b5-1f2d-4c38-b51e-dcd0e726edb3')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_source_dest_check_attribute(self):
|
||||
vpc_id, subnet_id = self.create_vpc_and_subnet('10.30.0.0/24')
|
||||
|
||||
instance_id = self.run_instance(SubnetId=subnet_id)
|
||||
|
||||
def do_check(value):
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck')
|
||||
self.assertIn('SourceDestCheck', data)
|
||||
self.assertEqual(value, data['SourceDestCheck'].get('Value'))
|
||||
|
||||
do_check(True)
|
||||
|
||||
self.client.modify_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck',
|
||||
Value='False')
|
||||
do_check(False)
|
||||
|
||||
self.client.reset_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck')
|
||||
do_check(True)
|
||||
|
||||
self.client.modify_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='sourceDestCheck',
|
||||
Value='False')
|
||||
do_check(False)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('a2640ab1-6aaa-4626-9f23-4aba52e3b88a')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
@testtools.skipUnless(CONF.aws.instance_type_alt,
|
||||
"Alternative instance type is not defined")
|
||||
@testtools.skipUnless(CONF.aws.instance_type_alt != CONF.aws.instance_type,
|
||||
"Alternative instance type is not defined")
|
||||
def test_instance_type_attribute(self):
|
||||
instance_id = self.run_instance(ImageId=CONF.aws.ebs_image_id)
|
||||
|
||||
self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
instance = self.get_instance(instance_id)
|
||||
self.assertEqual(CONF.aws.instance_type, instance['InstanceType'])
|
||||
|
||||
self.client.modify_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='instanceType',
|
||||
Value=CONF.aws.instance_type)
|
||||
instance = self.get_instance(instance_id)
|
||||
self.assertEqual(CONF.aws.instance_type, instance['InstanceType'])
|
||||
|
||||
self.client.modify_instance_attribute(
|
||||
InstanceId=instance_id,
|
||||
InstanceType={'Value': CONF.aws.instance_type_alt})
|
||||
instance = self.get_instance(instance_id)
|
||||
self.assertEqual(CONF.aws.instance_type_alt, instance['InstanceType'])
|
||||
|
||||
self.client.start_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
self.assertEqual(CONF.aws.instance_type_alt, instance['InstanceType'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
|
@ -1,252 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class InstanceTest(base.EC2TestCase):
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(InstanceTest, cls).setUpClass()
|
||||
if not CONF.aws.image_id:
|
||||
raise cls.skipException('aws image_id does not provided')
|
||||
cls.zone = CONF.aws.aws_zone
|
||||
|
||||
@decorators.idempotent_id('5604e461-c36a-4fea-84bc-eddfe702ae4f')
|
||||
def test_create_delete_instance(self):
|
||||
instance_type = CONF.aws.instance_type
|
||||
image_id = CONF.aws.image_id
|
||||
data = self.client.run_instances(
|
||||
ImageId=image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.assertEqual(1, len(data['Instances']))
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
data = self.client.describe_instances(InstanceIds=[instance_id])
|
||||
reservations = data.get('Reservations', [])
|
||||
self.assertNotEmpty(reservations)
|
||||
instances = reservations[0].get('Instances', [])
|
||||
self.assertEqual(1, len(instances))
|
||||
self.assertEqual(1, len(instances[0]['SecurityGroups']))
|
||||
groups = reservations[0].get('Groups', [])
|
||||
if base.TesterStateHolder().get_ec2_enabled():
|
||||
self.assertEqual(1, len(groups))
|
||||
self.assertEqual(groups[0]['GroupName'],
|
||||
instances[0]['SecurityGroups'][0]['GroupName'])
|
||||
else:
|
||||
self.assertEqual(0, len(groups))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
# NOTE(andrey-mp): There is difference between Openstack and Amazon.
|
||||
# Amazon returns instance in 'terminated' state some time after
|
||||
# instance deletion. But Openstack doesn't return such instance.
|
||||
|
||||
@decorators.idempotent_id('40b273e5-3d43-4529-99b0-da5dd7e6764e')
|
||||
def test_create_idempotent_instance(self):
|
||||
client_token = data_utils.rand_name('t')
|
||||
instance_type = CONF.aws.instance_type
|
||||
image_id = CONF.aws.image_id
|
||||
data = self.client.run_instances(
|
||||
ImageId=image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1,
|
||||
ClientToken=client_token)
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.assertEqual(1, len(data['Instances']))
|
||||
reservation_id = data['ReservationId']
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
data = self.client.run_instances(
|
||||
ImageId=image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1,
|
||||
ClientToken=client_token)
|
||||
|
||||
# NOTE(andrey-mp): if idempotent run will fail this will terminate
|
||||
# second instance
|
||||
self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[data['Instances'][0]['InstanceId']])
|
||||
|
||||
self.assertEqual(1, len(data['Instances']))
|
||||
self.assertEqual(reservation_id, data['ReservationId'])
|
||||
self.assertEqual(instance_id, data['Instances'][0]['InstanceId'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('4c3c709a-72e2-4c87-bab2-e3a16fc5d1fe')
|
||||
def test_describe_instances_filter(self):
|
||||
instance_type = CONF.aws.instance_type
|
||||
image_id = CONF.aws.image_id
|
||||
data = self.client.run_instances(
|
||||
ImageId=image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
# NOTE(andrey-mp): by real id
|
||||
data = self.client.describe_instances(InstanceIds=[instance_id])
|
||||
self._assert_instance(data, instance_id)
|
||||
instances = data['Reservations'][0]['Instances']
|
||||
private_dns = instances[0]['PrivateDnsName']
|
||||
private_ip = instances[0]['PrivateIpAddress']
|
||||
|
||||
# NOTE(andrey-mp): by fake id
|
||||
self.assertRaises('InvalidInstanceID.NotFound',
|
||||
self.client.describe_instances,
|
||||
InstanceIds=['i-0'])
|
||||
|
||||
# NOTE(andrey-mp): by private ip
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-ip-address', 'Values': ['1.2.3.4']}])
|
||||
self.assertEqual(0, len(data['Reservations']))
|
||||
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-ip-address', 'Values': [private_ip]}])
|
||||
self._assert_instance(data, instance_id)
|
||||
|
||||
# NOTE(andrey-mp): by private dns
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-dns-name', 'Values': ['fake.com']}])
|
||||
self.assertEqual(0, len(data['Reservations']))
|
||||
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-dns-name', 'Values': [private_dns]}])
|
||||
self._assert_instance(data, instance_id)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
def _assert_instance(self, data, instance_id):
|
||||
reservations = data.get('Reservations', [])
|
||||
self.assertNotEmpty(reservations)
|
||||
instances = reservations[0].get('Instances', [])
|
||||
self.assertNotEmpty(instances)
|
||||
self.assertEqual(instance_id, instances[0]['InstanceId'])
|
||||
|
||||
@decorators.idempotent_id('d40bf881-4220-46a9-b04a-fca9054c9731')
|
||||
def test_get_password_data_and_console_output(self):
|
||||
instance_type = CONF.aws.instance_type
|
||||
image_id = CONF.aws.image_id
|
||||
data = self.client.run_instances(
|
||||
ImageId=image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
data = self.client.get_password_data(InstanceId=instance_id)
|
||||
self.assertEqual(instance_id, data['InstanceId'])
|
||||
self.assertIsNotNone(data['Timestamp'])
|
||||
self.assertIn('PasswordData', data)
|
||||
|
||||
def _wait_for_output(*args, **kwargs):
|
||||
data = self.client.get_console_output(*args, **kwargs)
|
||||
self.assertIn('Output', data)
|
||||
|
||||
waiter = base.EC2Waiter(_wait_for_output)
|
||||
waiter.wait_no_exception(InstanceId=instance_id)
|
||||
|
||||
data = self.client.get_console_output(InstanceId=instance_id)
|
||||
self.assertEqual(instance_id, data['InstanceId'])
|
||||
self.assertIsNotNone(data['Timestamp'])
|
||||
self.assertIn('Output', data)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('5947ccaa-a519-46f4-9d58-ceb79042266a')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_stop_instance(self):
|
||||
instance_type = CONF.aws.instance_type
|
||||
image_id = CONF.aws.ebs_image_id
|
||||
data = self.client.run_instances(
|
||||
ImageId=image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
data = self.client.stop_instances(InstanceIds=[instance_id])
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
instances = data['StoppingInstances']
|
||||
self.assertEqual(1, len(instances))
|
||||
instance = instances[0]
|
||||
self.assertEqual(instance_id, instance['InstanceId'])
|
||||
self.assertEqual('running', instance['PreviousState']['Name'])
|
||||
self.assertEqual('stopping', instance['CurrentState']['Name'])
|
||||
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('0f29affb-eae5-42be-9b52-d28a17ba7107')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Openstack doesn't assign public ip automatically for new instance")
|
||||
def test_public_ip_is_assigned(self):
|
||||
"""Is public IP assigned to launched instnace?"""
|
||||
instance_type = CONF.aws.instance_type
|
||||
image_id = CONF.aws.image_id
|
||||
data = self.client.run_instances(
|
||||
ImageId=image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': self.zone}, MinCount=1, MaxCount=1)
|
||||
self.assertEqual(1, len(data['Instances']))
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
self.assertIsNotNone(instance.get('PublicIpAddress'))
|
||||
self.assertIsNotNone(instance.get('PrivateIpAddress'))
|
||||
self.assertNotEqual(instance.get('PublicIpAddress'),
|
||||
instance.get('PrivateIpAddress'))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
|
@ -1,92 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class InstanceWithEBSTest(base.EC2TestCase):
|
||||
|
||||
@decorators.idempotent_id('a5cad848-bed2-4dcb-8ba0-987bb7e9c487')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_create_get_delete_ebs_instance(self):
|
||||
"""Launch EBS-backed instance, check results, and terminate it."""
|
||||
instance_id = self.run_instance(ImageId=CONF.aws.ebs_image_id)
|
||||
instance = self.get_instance(instance_id)
|
||||
|
||||
self.assertEqual('ebs', instance.get('RootDeviceType'))
|
||||
self.assertIsNotNone(instance.get('RootDeviceName'))
|
||||
bdms = instance.get('BlockDeviceMappings')
|
||||
self.assertIsNotNone(bdms)
|
||||
rdn = instance['RootDeviceName']
|
||||
bdt = [bdt for bdt in bdms if bdt['DeviceName'] == rdn]
|
||||
self.assertEqual(1, len(bdt))
|
||||
ebs = bdt[0]['Ebs']
|
||||
self.assertIsNotNone(ebs)
|
||||
volume_id = ebs.get('VolumeId')
|
||||
self.assertIsNotNone(volume_id)
|
||||
self.assertEqual('attached', ebs.get('Status'))
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
self.assertTrue(ebs.get('AttachTime'))
|
||||
self.assertTrue(ebs.get('DeleteOnTermination'))
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
|
||||
data = self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('b6226b7b-d965-4c3a-b2a8-48add794c194')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_create_root_volume_snapshot(self):
|
||||
"""Create snapshot of root volume of EBS-backed instance."""
|
||||
instance_id = self.run_instance(ImageId=CONF.aws.ebs_image_id)
|
||||
|
||||
bdt = self.get_instance_bdm(instance_id, None)
|
||||
self.assertIsNotNone(bdt)
|
||||
volume_id = bdt['Ebs'].get('VolumeId')
|
||||
self.assertIsNotNone(volume_id)
|
||||
|
||||
self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
|
||||
kwargs = {
|
||||
'VolumeId': data['Volumes'][0]['VolumeId'],
|
||||
'Description': 'Description'
|
||||
}
|
||||
data = self.client.create_snapshot(*[], **kwargs)
|
||||
snapshot_id = data['SnapshotId']
|
||||
res_clean_s = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
data = self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(res_clean_s)
|
||||
self.get_snapshot_waiter().wait_delete(snapshot_id)
|
||||
|
||||
data = self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
|
@ -1,282 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class InstanceInVPCTest(base.EC2TestCase):
|
||||
|
||||
VPC_CIDR = '10.16.0.0/20'
|
||||
vpc_id = None
|
||||
SUBNET_CIDR = '10.16.0.0/24'
|
||||
subnet_id = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(InstanceInVPCTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR)
|
||||
cls.vpc_id = data['Vpc']['VpcId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc, VpcId=cls.vpc_id)
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id)
|
||||
|
||||
aws_zone = CONF.aws.aws_zone
|
||||
data = cls.client.create_subnet(VpcId=cls.vpc_id,
|
||||
CidrBlock=cls.SUBNET_CIDR,
|
||||
AvailabilityZone=aws_zone)
|
||||
cls.subnet_id = data['Subnet']['SubnetId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_subnet,
|
||||
SubnetId=cls.subnet_id)
|
||||
cls.get_subnet_waiter().wait_available(cls.subnet_id)
|
||||
|
||||
@decorators.idempotent_id('af8bd493-4a68-49e7-a3d1-326251b8d16e')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_create_delete_instance(self):
|
||||
instance_id = self.run_instance(SubnetId=self.subnet_id)
|
||||
|
||||
data = self.client.describe_instances(InstanceIds=[instance_id])
|
||||
reservations = data.get('Reservations', [])
|
||||
self.assertNotEmpty(reservations)
|
||||
instances = reservations[0].get('Instances', [])
|
||||
self.assertNotEmpty(instances)
|
||||
instance = instances[0]
|
||||
self.assertEqual(self.vpc_id, instance['VpcId'])
|
||||
self.assertEqual(self.subnet_id, instance['SubnetId'])
|
||||
self.assertTrue(instance['SourceDestCheck'])
|
||||
self.assertEqual(1, len(instance['NetworkInterfaces']))
|
||||
ni = instance['NetworkInterfaces'][0]
|
||||
self.assertEqual(1, len(ni['Groups']))
|
||||
self.assertIsNotNone(ni['MacAddress'])
|
||||
self.assertIsNotNone(ni['PrivateIpAddress'])
|
||||
self.assertTrue(ni['SourceDestCheck'])
|
||||
self.assertEqual('in-use', ni['Status'])
|
||||
self.assertEqual(self.vpc_id, ni['VpcId'])
|
||||
self.assertEqual(self.subnet_id, ni['SubnetId'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
# NOTE(andrey-mp): There is difference between Openstack and Amazon.
|
||||
# Amazon returns instance in 'terminated' state some time after
|
||||
# instance deletion. But Openstack doesn't return such instance.
|
||||
|
||||
@decorators.idempotent_id('17ba6206-3044-4e51-9e9b-f5d5728cc047')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_describe_instances_filter(self):
|
||||
instance_id = self.run_instance(SubnetId=self.subnet_id)
|
||||
|
||||
data = self.client.describe_instances(InstanceIds=[instance_id])
|
||||
self.assert_instance(data, instance_id)
|
||||
instances = data['Reservations'][0]['Instances']
|
||||
private_dns = instances[0]['PrivateDnsName']
|
||||
private_ip = instances[0]['PrivateIpAddress']
|
||||
|
||||
# NOTE(andrey-mp): by private ip
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-ip-address', 'Values': ['1.2.3.4']}])
|
||||
self.assertEqual(0, len(data['Reservations']))
|
||||
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-ip-address', 'Values': [private_ip]}])
|
||||
self.assert_instance(data, instance_id)
|
||||
|
||||
# NOTE(andrey-mp): by private dns
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-dns-name', 'Values': ['fake.com']}])
|
||||
self.assertEqual(0, len(data['Reservations']))
|
||||
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'private-dns-name', 'Values': [private_dns]}])
|
||||
self.assert_instance(data, instance_id)
|
||||
|
||||
# NOTE(andrey-mp): by subnet id
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'subnet-id', 'Values': ['subnet-0']}])
|
||||
self.assertEqual(0, len(data['Reservations']))
|
||||
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'subnet-id', 'Values': [self.subnet_id]}])
|
||||
self.assert_instance(data, instance_id)
|
||||
|
||||
# NOTE(andrey-mp): by vpc id
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': ['vpc-0']}])
|
||||
self.assertEqual(0, len(data['Reservations']))
|
||||
|
||||
data = self.client.describe_instances(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [self.vpc_id]}])
|
||||
self.assert_instance(data, instance_id)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
def assert_instance(self, data, instance_id):
|
||||
reservations = data.get('Reservations', [])
|
||||
self.assertNotEmpty(reservations)
|
||||
instances = reservations[0].get('Instances', [])
|
||||
self.assertNotEmpty(instances)
|
||||
self.assertEqual(instance_id, instances[0]['InstanceId'])
|
||||
|
||||
@decorators.idempotent_id('60ceda8b-85ae-47a7-807b-c4a4dd05a13b')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_create_instance_with_two_interfaces(self):
|
||||
kwargs = {
|
||||
'SubnetId': self.subnet_id,
|
||||
}
|
||||
data = self.client.create_network_interface(*[], **kwargs)
|
||||
ni_id1 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
clean_ni1 = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id1)
|
||||
self.get_network_interface_waiter().wait_available(ni_id1)
|
||||
|
||||
kwargs = {
|
||||
'SubnetId': self.subnet_id,
|
||||
}
|
||||
data = self.client.create_network_interface(*[], **kwargs)
|
||||
ni_id2 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
clean_ni2 = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id2)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
|
||||
instance_id = self.run_instance(
|
||||
NetworkInterfaces=[{'NetworkInterfaceId': ni_id1,
|
||||
'DeviceIndex': 0},
|
||||
{'NetworkInterfaceId': ni_id2,
|
||||
'DeviceIndex': 2}])
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
nis = instance.get('NetworkInterfaces', [])
|
||||
self.assertEqual(2, len(nis))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.get_network_interface_waiter().wait_available(ni_id1)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
|
||||
self.client.delete_network_interface(
|
||||
NetworkInterfaceId=ni_id2)
|
||||
self.cancelResourceCleanUp(clean_ni2)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id2)
|
||||
|
||||
self.client.delete_network_interface(
|
||||
NetworkInterfaceId=ni_id1)
|
||||
self.cancelResourceCleanUp(clean_ni1)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id1)
|
||||
|
||||
@decorators.idempotent_id('a7dc520a-e828-4347-91e1-385c4e0e6070')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_create_instance_with_private_ip(self):
|
||||
ip = '10.16.0.12'
|
||||
|
||||
instance_id = self.run_instance(SubnetId=self.subnet_id,
|
||||
PrivateIpAddress=ip)
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
self.assertEqual(ip, instance['PrivateIpAddress'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('582ac8ed-58e7-4f27-bd65-35b999241c63')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_create_instance_with_invalid_params(self):
|
||||
def _rollback(fn_data):
|
||||
self.client.terminate_instances(
|
||||
InstanceIds=[fn_data['Instances'][0]['InstanceId']])
|
||||
|
||||
kwargs = {
|
||||
'ImageId': CONF.aws.image_id,
|
||||
'InstanceType': CONF.aws.instance_type,
|
||||
'MinCount': 1,
|
||||
'MaxCount': 1,
|
||||
'PrivateIpAddress': '10.16.1.2'
|
||||
}
|
||||
ex_str = ('InvalidParameterCombination'
|
||||
if base.TesterStateHolder().get_ec2_enabled() else
|
||||
'InvalidParameterValue')
|
||||
self.assertRaises(ex_str,
|
||||
self.client.run_instances, rollback_fn=_rollback,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'ImageId': CONF.aws.image_id,
|
||||
'InstanceType': CONF.aws.instance_type,
|
||||
'MinCount': 1,
|
||||
'MaxCount': 1,
|
||||
'SubnetId': self.subnet_id,
|
||||
'PrivateIpAddress': '10.16.1.12'
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.run_instances, rollback_fn=_rollback,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'SubnetId': self.subnet_id,
|
||||
}
|
||||
data = self.client.create_network_interface(*[], **kwargs)
|
||||
ni_id1 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
self.addResourceCleanUp(self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id1)
|
||||
self.get_network_interface_waiter().wait_available(ni_id1)
|
||||
|
||||
kwargs = {
|
||||
'SubnetId': self.subnet_id,
|
||||
}
|
||||
data = self.client.create_network_interface(*[], **kwargs)
|
||||
ni_id2 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
self.addResourceCleanUp(self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id2)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
|
||||
# NOTE(andrey-mp): A network interface may not specify a network
|
||||
# interface ID and delete on termination as true
|
||||
kwargs = {
|
||||
'ImageId': CONF.aws.image_id,
|
||||
'InstanceType': CONF.aws.instance_type,
|
||||
'MinCount': 1,
|
||||
'MaxCount': 1,
|
||||
'NetworkInterfaces': [{'NetworkInterfaceId': ni_id1,
|
||||
'DeviceIndex': 0,
|
||||
'DeleteOnTermination': True}]
|
||||
}
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.run_instances, rollback_fn=_rollback,
|
||||
**kwargs)
|
||||
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
# NOTE(andrey-mp): Each network interface requires a device index.
|
||||
kwargs = {
|
||||
'ImageId': CONF.aws.image_id,
|
||||
'InstanceType': CONF.aws.instance_type,
|
||||
'MinCount': 1,
|
||||
'MaxCount': 1,
|
||||
'NetworkInterfaces': [{'NetworkInterfaceId': ni_id1},
|
||||
{'NetworkInterfaceId': ni_id2}]
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.run_instances, rollback_fn=_rollback,
|
||||
**kwargs)
|
|
@ -1,223 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class InternetGatewayTest(base.EC2TestCase):
|
||||
|
||||
VPC_CIDR = '10.4.0.0/20'
|
||||
VPC_CIDR_ALT = '10.5.0.0/20'
|
||||
vpc_id = None
|
||||
vpc_id_alt = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(InternetGatewayTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR)
|
||||
cls.vpc_id = data['Vpc']['VpcId']
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id)
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc, VpcId=cls.vpc_id)
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR_ALT)
|
||||
cls.vpc_id_alt = data['Vpc']['VpcId']
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id_alt)
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc,
|
||||
VpcId=cls.vpc_id_alt)
|
||||
|
||||
@decorators.idempotent_id('f2d40306-4b18-4e17-90a5-371db0ddc7cb')
|
||||
def test_create_attach_internet_gateway(self):
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_internet_gateway, InternetGatewayId=gw_id)
|
||||
self.assertEmpty(data['InternetGateway'].get('Attachments', []))
|
||||
|
||||
data = self.client.attach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.detach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
self.assertRaises('InvalidInternetGatewayID.NotFound',
|
||||
self.client.describe_internet_gateways,
|
||||
InternetGatewayIds=[gw_id])
|
||||
|
||||
@decorators.idempotent_id('f092b63d-9460-4d8f-ba8a-bcd380666033')
|
||||
def test_delete_attached_internet_gateway(self):
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_internet_gateway, InternetGatewayId=gw_id)
|
||||
self.assertEmpty(data['InternetGateway'].get('Attachments', []))
|
||||
|
||||
data = self.client.attach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
self.assertRaises('DependencyViolation',
|
||||
self.client.delete_internet_gateway,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.detach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('89700013-5753-4608-8245-4fc99fbb67ea')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Another error code returned - InvalidParameterValue")
|
||||
def test_attach_detach_invalid_internet_gateway(self):
|
||||
gw_id = "gw-1"
|
||||
self.assertRaises('InvalidInternetGatewayID.NotFound',
|
||||
self.client.attach_internet_gateway,
|
||||
VpcId=self.vpc_id, InternetGatewayId=gw_id)
|
||||
|
||||
self.assertRaises('InvalidInternetGatewayID.NotFound',
|
||||
self.client.detach_internet_gateway,
|
||||
VpcId=self.vpc_id, InternetGatewayId=gw_id)
|
||||
|
||||
@decorators.idempotent_id('e3e4d8c4-8f62-43e8-a24d-bfd292b4144c')
|
||||
def test_double_attach_internet_gateway(self):
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_internet_gateway, InternetGatewayId=gw_id)
|
||||
self.assertEmpty(data['InternetGateway'].get('Attachments', []))
|
||||
|
||||
data = self.client.attach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
self.assertRaises('Resource.AlreadyAssociated',
|
||||
self.client.attach_internet_gateway,
|
||||
VpcId=self.vpc_id, InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.detach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('d8f3a488-a4ba-4ed5-998c-3dc6f43d6d9e')
|
||||
def test_attach_one_internet_gateway_to_two_vpcs(self):
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_internet_gateway, InternetGatewayId=gw_id)
|
||||
self.assertEmpty(data['InternetGateway'].get('Attachments', []))
|
||||
|
||||
data = self.client.attach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
self.assertRaises('Resource.AlreadyAssociated',
|
||||
self.client.attach_internet_gateway,
|
||||
VpcId=self.vpc_id_alt, InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.detach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('b86f338c-613e-4cd7-9742-07c86864b0da')
|
||||
def test_describe_internet_gateways_base(self):
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_internet_gateway, InternetGatewayId=gw_id)
|
||||
self.assertEmpty(data['InternetGateway'].get('Attachments', []))
|
||||
|
||||
data = self.client.attach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
self.addResourceCleanUp(self.client.detach_internet_gateway,
|
||||
VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
time.sleep(2)
|
||||
# NOTE(andrey-mp): by real id
|
||||
data = self.client.describe_internet_gateways(
|
||||
InternetGatewayIds=[gw_id])
|
||||
self.assertEqual(1, len(data['InternetGateways']))
|
||||
|
||||
# NOTE(andrey-mp): by fake id
|
||||
self.assertRaises('InvalidInternetGatewayID.NotFound',
|
||||
self.client.describe_internet_gateways,
|
||||
InternetGatewayIds=['igw-0'])
|
||||
|
||||
data = self.client.detach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('3f141c56-9ee6-46bf-9c14-0d922ed8a482')
|
||||
def test_describe_internet_gateways_filters(self):
|
||||
# NOTE(andrey-mp): by filter real vpc-id before creation
|
||||
data = self.client.describe_internet_gateways(
|
||||
Filters=[{'Name': 'attachment.vpc-id', 'Values': [self.vpc_id]}])
|
||||
self.assertEqual(0, len(data['InternetGateways']))
|
||||
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_internet_gateway, InternetGatewayId=gw_id)
|
||||
self.assertEmpty(data['InternetGateway'].get('Attachments', []))
|
||||
|
||||
data = self.client.attach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
self.addResourceCleanUp(self.client.detach_internet_gateway,
|
||||
VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
time.sleep(2)
|
||||
# NOTE(andrey-mp): by filter real vpc-id
|
||||
data = self.client.describe_internet_gateways(
|
||||
Filters=[{'Name': 'attachment.vpc-id', 'Values': [self.vpc_id]}])
|
||||
self.assertEqual(1, len(data['InternetGateways']))
|
||||
self.assertEqual(gw_id,
|
||||
data['InternetGateways'][0]['InternetGatewayId'])
|
||||
|
||||
# NOTE(andrey-mp): by filter fake vpc-id
|
||||
data = self.client.describe_internet_gateways(
|
||||
Filters=[{'Name': 'attachment.vpc-id', 'Values': ['vpc-0']}])
|
||||
self.assertEqual(0, len(data['InternetGateways']))
|
||||
|
||||
# NOTE(andrey-mp): by fake filter
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_internet_gateways,
|
||||
Filters=[{'Name': 'fake', 'Values': ['fake']}])
|
||||
|
||||
data = self.client.detach_internet_gateway(VpcId=self.vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
data = self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
|
@ -1,149 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class KeyPairTest(base.EC2TestCase):
|
||||
|
||||
@decorators.idempotent_id('15cfd866-d6bb-473a-9b8a-6420900a5ca3')
|
||||
def test_create_delete_key_pair(self):
|
||||
keyName = 'Test key'
|
||||
data = self.client.create_key_pair(KeyName=keyName)
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_key_pair,
|
||||
KeyName=keyName)
|
||||
|
||||
self.assertEqual(keyName, data['KeyName'])
|
||||
self.assertIsNotNone(data.get('KeyFingerprint'))
|
||||
self.assertGreater(len(data['KeyFingerprint']), 0)
|
||||
self.assertGreater(len(data.get('KeyMaterial')), 0)
|
||||
|
||||
data = self.client.delete_key_pair(KeyName=keyName)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('05478a51-1505-42a8-8c7d-4fd7e32c467e')
|
||||
def test_create_duplicate_key_pair(self):
|
||||
keyName = 'Test key'
|
||||
self.client.create_key_pair(KeyName=keyName)
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_key_pair,
|
||||
KeyName=keyName)
|
||||
|
||||
self.assertRaises('InvalidKeyPair.Duplicate',
|
||||
self.client.create_key_pair,
|
||||
KeyName=keyName)
|
||||
|
||||
self.client.delete_key_pair(KeyName=keyName)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('43d87b6e-6667-4d19-8c0b-e73901105bb7')
|
||||
def test_describe_key_pairs(self):
|
||||
keyName = 'Test key'
|
||||
data = self.client.create_key_pair(KeyName=keyName)
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_key_pair,
|
||||
KeyName=keyName)
|
||||
self.assertIsNotNone(data.get('KeyFingerprint'))
|
||||
self.assertGreater(len(data['KeyFingerprint']), 0)
|
||||
fingerprint = data.get('KeyFingerprint')
|
||||
|
||||
data = self.client.describe_key_pairs(KeyNames=[keyName])
|
||||
self.assertEqual(1, len(data.get('KeyPairs')))
|
||||
data = data['KeyPairs'][0]
|
||||
self.assertEqual(keyName, data['KeyName'])
|
||||
self.assertIsNotNone(data.get('KeyFingerprint'))
|
||||
self.assertGreater(len(data['KeyFingerprint']), 0)
|
||||
self.assertIsNone(data.get('KeyMaterial'))
|
||||
|
||||
data = self.client.describe_key_pairs(
|
||||
Filters=[{'Name': 'key-name', 'Values': [keyName]}])
|
||||
self.assertEqual(1, len(data.get('KeyPairs')))
|
||||
self.assertEqual(keyName, data['KeyPairs'][0]['KeyName'])
|
||||
|
||||
data = self.client.describe_key_pairs(
|
||||
Filters=[{'Name': 'fingerprint', 'Values': [fingerprint]}])
|
||||
self.assertEqual(1, len(data.get('KeyPairs')))
|
||||
self.assertEqual(keyName, data['KeyPairs'][0]['KeyName'])
|
||||
|
||||
self.assertRaises('InvalidKeyPair.NotFound',
|
||||
self.client.describe_key_pairs,
|
||||
KeyNames=['fake key'])
|
||||
|
||||
data = self.client.delete_key_pair(KeyName=keyName)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
self.assertRaises('InvalidKeyPair.NotFound',
|
||||
self.client.describe_key_pairs,
|
||||
KeyNames=[keyName])
|
||||
|
||||
# NOTE(andrey-mp): Amazon allows to delete absent key and returns 200
|
||||
self.client.delete_key_pair(KeyName=keyName)
|
||||
|
||||
@decorators.idempotent_id('0e51eec5-3f61-4d8a-89c9-8d098f381682')
|
||||
def test_import_empty_key_pair(self):
|
||||
keyName = 'Test key'
|
||||
publicKey = ''
|
||||
|
||||
def _rollback(fn_data):
|
||||
self.client.delete_key_pair(KeyName=keyName)
|
||||
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.import_key_pair,
|
||||
rollback_fn=_rollback,
|
||||
KeyName=keyName, PublicKeyMaterial=publicKey)
|
||||
|
||||
@decorators.idempotent_id('478c17e6-b7ca-4115-bee2-be279bdd0f65')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Different error code")
|
||||
def test_import_invalid_key_pair(self):
|
||||
keyName = 'Test key'
|
||||
publicKey = 'ssh-rsa JUNK test@ubuntu'
|
||||
|
||||
def _rollback():
|
||||
self.client.delete_key_pair(KeyName=keyName)
|
||||
|
||||
self.assertRaises('InvalidKey.Format',
|
||||
self.client.import_key_pair,
|
||||
rollback_fn=_rollback,
|
||||
KeyName=keyName, PublicKeyMaterial=publicKey)
|
||||
|
||||
@decorators.idempotent_id('eda525d6-144b-4840-b6ba-e18d93e3589f')
|
||||
def test_import_key_pair(self):
|
||||
keyName = 'Test key'
|
||||
publicKey = ("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCs"
|
||||
"Ne3/1ILNCqFyfYWDeTKLD6jEXC2OQHLmietMWW+/vd"
|
||||
"aZq7KZEwO0jhglaFjU1mpqq4Gz5RX156sCTNM9vRbw"
|
||||
"KAxfsdF9laBYVsex3m3Wmui3uYrKyumsoJn2g9GNnG1P"
|
||||
"I1mrVjZ61i0GY3khna+wzlTpCCmy5HNlrmbj3XLqBUpip"
|
||||
"TOXmsnr4sChzC53KCd8LXuwc1i/CZPvF+3XipvAgFSE53pCt"
|
||||
"LOeB1kYMOBaiUPLQTWXR3JpckqFIQwhIH0zoHlJvZE8hh90"
|
||||
"XcPojYN56tI0OlrGqojbediJYD0rUsJu4weZpbn8vilb3JuDY+jws"
|
||||
"snSA8wzBx3A/8y9Pp1B test@ubuntu")
|
||||
data = self.client.import_key_pair(KeyName=keyName,
|
||||
PublicKeyMaterial=publicKey)
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_key_pair,
|
||||
KeyName=keyName)
|
||||
|
||||
self.assertEqual(keyName, data['KeyName'])
|
||||
self.assertIsNotNone(data.get('KeyFingerprint'))
|
||||
self.assertGreater(len(data['KeyFingerprint']), 0)
|
||||
self.assertIsNone(data.get('KeyMaterial'))
|
||||
|
||||
self.client.delete_key_pair(KeyName=keyName)
|
||||
self.cancelResourceCleanUp(res_clean)
|
|
@ -1,582 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
import botocore.exceptions
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class NetworkInterfaceTest(base.EC2TestCase):
|
||||
|
||||
VPC_CIDR = '10.7.0.0/20'
|
||||
vpc_id = None
|
||||
SUBNET_CIDR = '10.7.0.0/28'
|
||||
subnet_id = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(NetworkInterfaceTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR)
|
||||
cls.vpc_id = data['Vpc']['VpcId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc, VpcId=cls.vpc_id)
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id)
|
||||
|
||||
aws_zone = CONF.aws.aws_zone
|
||||
data = cls.client.create_subnet(VpcId=cls.vpc_id,
|
||||
CidrBlock=cls.SUBNET_CIDR,
|
||||
AvailabilityZone=aws_zone)
|
||||
cls.subnet_id = data['Subnet']['SubnetId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_subnet,
|
||||
SubnetId=cls.subnet_id)
|
||||
cls.get_subnet_waiter().wait_available(cls.subnet_id)
|
||||
|
||||
def _wait_assignment(self, ni_id, data):
|
||||
# NOTE(andrey-mp): Amazon don't do it quickly and there is no way
|
||||
# to wait this request
|
||||
time.sleep(5)
|
||||
|
||||
@decorators.idempotent_id('d03f49b1-a77e-439b-96e2-5e152b968863')
|
||||
def test_delete_subnet_with_network_interface(self):
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id,
|
||||
CidrBlock='10.7.1.0/28')
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean_subnet = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
data = self.client.create_network_interface(SubnetId=subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean_ni = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
time.sleep(2)
|
||||
|
||||
self.assertRaises('DependencyViolation',
|
||||
self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean_ni)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean_subnet)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
@decorators.idempotent_id('e19e450d-5c24-47b1-9814-4a65a78e5a31')
|
||||
def test_create_network_interface(self):
|
||||
desc = data_utils.rand_name('ni')
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id,
|
||||
Description=desc)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
ni = data['NetworkInterface']
|
||||
self.assertEqual(self.vpc_id, ni['VpcId'])
|
||||
self.assertEqual(self.subnet_id, ni['SubnetId'])
|
||||
self.assertEqual(desc, ni['Description'])
|
||||
|
||||
self.assertNotEmpty(ni.get('Groups'))
|
||||
self.assertEqual('default', ni['Groups'][0]['GroupName'])
|
||||
|
||||
address = ni.get('PrivateIpAddress')
|
||||
self.assertIsNotNone(address)
|
||||
addresses = ni.get('PrivateIpAddresses')
|
||||
self.assertIsNotNone(addresses)
|
||||
self.assertEqual(1, len(addresses))
|
||||
self.assertTrue(addresses[0]['Primary'])
|
||||
self.assertEqual(address, addresses[0]['PrivateIpAddress'])
|
||||
|
||||
self.assertIsNotNone(ni.get('MacAddress'))
|
||||
self.assertIsNotNone(ni.get('OwnerId'))
|
||||
self.assertIsNotNone(ni.get('RequesterManaged'))
|
||||
self.assertIsNotNone(ni.get('SourceDestCheck'))
|
||||
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
self.assertRaises('InvalidNetworkInterfaceID.NotFound',
|
||||
self.client.describe_network_interfaces,
|
||||
NetworkInterfaceIds=[ni_id])
|
||||
|
||||
# TODO(andrey-mp): add creation with addresses
|
||||
|
||||
@decorators.idempotent_id('61e16648-7736-4647-b618-27d3f4f0c9c6')
|
||||
def test_create_max_network_interface(self):
|
||||
# NOTE(andrey-mp): wait some time while all ports will be deleted
|
||||
# for this subnet(that are deleting after previous test)
|
||||
time.sleep(5)
|
||||
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count_before = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
addresses = []
|
||||
while True:
|
||||
try:
|
||||
data = self.client.create_network_interface(
|
||||
SubnetId=self.subnet_id)
|
||||
except botocore.exceptions.ClientError as e:
|
||||
error_code = e.response['Error']['Code']
|
||||
self.assertEqual('InsufficientFreeAddressesInSubnet',
|
||||
error_code, e.message)
|
||||
break
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id)
|
||||
addresses.append((ni_id, res_clean))
|
||||
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count_after = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
# NOTE(andrey-mp): This is strange but Amazon can't create last NI
|
||||
# and Openstack can
|
||||
self.assertIn(count_after, [0, 1])
|
||||
self.assertEqual(len(addresses), count_before - count_after)
|
||||
|
||||
for addr in addresses:
|
||||
self.client.delete_network_interface(NetworkInterfaceId=addr[0])
|
||||
self.cancelResourceCleanUp(addr[1])
|
||||
self.get_network_interface_waiter().wait_delete(addr[0])
|
||||
|
||||
@decorators.idempotent_id('8c174e5f-e377-4bf2-9315-b868a8199c17')
|
||||
def test_unassign_primary_addresses(self):
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
primary_address = data['NetworkInterface'].get('PrivateIpAddress')
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.unassign_private_ip_addresses,
|
||||
NetworkInterfaceId=ni_id,
|
||||
PrivateIpAddresses=[primary_address])
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
@decorators.idempotent_id('de0d0375-d99a-476c-939a-0e15c4e431a8')
|
||||
def test_assign_unassign_private_addresses_by_count(self):
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
data = self.client.assign_private_ip_addresses(
|
||||
NetworkInterfaceId=ni_id,
|
||||
SecondaryPrivateIpAddressCount=2)
|
||||
self._wait_assignment(ni_id, data)
|
||||
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count_after = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
self.assertEqual(count - 3, count_after)
|
||||
|
||||
data = self.client.describe_network_interfaces(
|
||||
NetworkInterfaceIds=[ni_id])
|
||||
|
||||
addresses = []
|
||||
for addr in data['NetworkInterfaces'][0]['PrivateIpAddresses']:
|
||||
if not addr['Primary']:
|
||||
addresses.append(addr['PrivateIpAddress'])
|
||||
self.assertEqual(2, len(addresses))
|
||||
|
||||
data = self.client.unassign_private_ip_addresses(
|
||||
NetworkInterfaceId=ni_id,
|
||||
PrivateIpAddresses=addresses)
|
||||
self._wait_assignment(ni_id, data)
|
||||
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count_after = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
self.assertEqual(count - 1, count_after)
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
@decorators.idempotent_id('5d7bda42-d23e-4cbf-9e66-8ca052ac28ff')
|
||||
def test_assign_unassign_private_addresses_by_addresses(self):
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
ni = self.client.describe_network_interfaces(
|
||||
NetworkInterfaceIds=[ni_id])['NetworkInterfaces']
|
||||
ni_addr = ni[0]['PrivateIpAddresses'][0]['PrivateIpAddress']
|
||||
|
||||
# add two more addresses to interface.
|
||||
# check that they does not equal to current.
|
||||
addresses = []
|
||||
for i in range(10, 13):
|
||||
addr = '10.7.0.%d' % i
|
||||
if addr != ni_addr:
|
||||
addresses.append(addr)
|
||||
if len(addresses) >= 2:
|
||||
break
|
||||
data = self.client.assign_private_ip_addresses(
|
||||
NetworkInterfaceId=ni_id,
|
||||
PrivateIpAddresses=addresses)
|
||||
self._wait_assignment(ni_id, data)
|
||||
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count_after = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
# NOTE(Alex): Amazon misses 1 IP address by some reason.
|
||||
self.assertIn(count_after, [count - 3, count - 4])
|
||||
|
||||
data = self.client.describe_network_interfaces(
|
||||
NetworkInterfaceIds=[ni_id])
|
||||
|
||||
assigned_addresses = []
|
||||
for addr in data['NetworkInterfaces'][0]['PrivateIpAddresses']:
|
||||
if not addr['Primary']:
|
||||
self.assertIn(addr['PrivateIpAddress'], addresses)
|
||||
assigned_addresses.append(addr['PrivateIpAddress'])
|
||||
self.assertEqual(2, len(assigned_addresses))
|
||||
|
||||
data = self.client.unassign_private_ip_addresses(
|
||||
NetworkInterfaceId=ni_id,
|
||||
PrivateIpAddresses=addresses)
|
||||
self._wait_assignment(ni_id, data)
|
||||
|
||||
data = self.client.describe_subnets(SubnetIds=[self.subnet_id])
|
||||
count_after = data['Subnets'][0]['AvailableIpAddressCount']
|
||||
self.assertIn(count_after, [count - 1, count - 2])
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
@decorators.idempotent_id('0c514bb4-5800-4db0-9032-0aa3ab998612')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_attach_network_interface(self):
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
self.addResourceCleanUp(self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id)
|
||||
ni = data['NetworkInterface']
|
||||
address = ni.get('PrivateIpAddress')
|
||||
self.assertIsNotNone(address)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
instance_id = self.run_instance(SubnetId=self.subnet_id)
|
||||
|
||||
# NOTE(andrey-mp): Amazon can't attach to device index = 0
|
||||
kwargs = {
|
||||
'DeviceIndex': 0,
|
||||
'InstanceId': instance_id,
|
||||
'NetworkInterfaceId': ni_id
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.attach_network_interface,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DeviceIndex': 2,
|
||||
'InstanceId': instance_id,
|
||||
'NetworkInterfaceId': ni_id
|
||||
}
|
||||
data = self.client.attach_network_interface(*[], **kwargs)
|
||||
attachment_id = data['AttachmentId']
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
nis = instance.get('NetworkInterfaces', [])
|
||||
self.assertEqual(2, len(nis))
|
||||
ids = [nis[0]['Attachment']['AttachmentId'],
|
||||
nis[1]['Attachment']['AttachmentId']]
|
||||
self.assertIn(attachment_id, ids)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id)
|
||||
|
||||
self.client.detach_network_interface(AttachmentId=attachment_id)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('381c9995-bc83-4e7e-b716-25a451660ace')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_network_interfaces_are_not_deleted_on_termination(self):
|
||||
instance_id = self.run_instance(SubnetId=self.subnet_id)
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
nis = instance.get('NetworkInterfaces', [])
|
||||
self.assertEqual(1, len(nis))
|
||||
self.assertTrue(nis[0]['Attachment']['DeleteOnTermination'])
|
||||
ni_id = nis[0]['NetworkInterfaceId']
|
||||
attachment_id = nis[0]['Attachment']['AttachmentId']
|
||||
|
||||
kwargs = {
|
||||
'NetworkInterfaceId': ni_id,
|
||||
'Attachment': {
|
||||
'AttachmentId': attachment_id,
|
||||
'DeleteOnTermination': False,
|
||||
}
|
||||
}
|
||||
self.client.modify_network_interface_attribute(*[], **kwargs)
|
||||
clean_ni = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id2 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
clean_ni2 = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id2)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
kwargs = {
|
||||
'DeviceIndex': 2,
|
||||
'InstanceId': instance_id,
|
||||
'NetworkInterfaceId': ni_id2
|
||||
}
|
||||
data = self.client.attach_network_interface(*[], **kwargs)
|
||||
attachment_id = data['AttachmentId']
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
nis = instance.get('NetworkInterfaces', [])
|
||||
self.assertEqual(2, len(nis))
|
||||
ni = nis[0]
|
||||
if ni['Attachment']['AttachmentId'] != attachment_id:
|
||||
ni = nis[1]
|
||||
self.assertEqual(attachment_id, ni['Attachment']['AttachmentId'])
|
||||
self.assertFalse(ni['Attachment']['DeleteOnTermination'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(clean_ni)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id2)
|
||||
self.cancelResourceCleanUp(clean_ni2)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id2)
|
||||
|
||||
@decorators.idempotent_id('de910bc7-008a-40c2-b4b2-4587a489fc1c')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_network_interfaces_are_deleted_on_termination(self):
|
||||
instance_id = self.run_instance(SubnetId=self.subnet_id)
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
nis = instance.get('NetworkInterfaces', [])
|
||||
self.assertEqual(1, len(nis))
|
||||
self.assertTrue(nis[0]['Attachment']['DeleteOnTermination'])
|
||||
ni_id = nis[0]['NetworkInterfaceId']
|
||||
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id2 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
self.addResourceCleanUp(self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id2)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
kwargs = {
|
||||
'DeviceIndex': 2,
|
||||
'InstanceId': instance_id,
|
||||
'NetworkInterfaceId': ni_id2
|
||||
}
|
||||
data = self.client.attach_network_interface(*[], **kwargs)
|
||||
attachment_id = data['AttachmentId']
|
||||
|
||||
kwargs = {
|
||||
'NetworkInterfaceId': ni_id2,
|
||||
'Attachment': {
|
||||
'AttachmentId': attachment_id,
|
||||
'DeleteOnTermination': True,
|
||||
}
|
||||
}
|
||||
self.client.modify_network_interface_attribute(*[], **kwargs)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id2)
|
||||
|
||||
@decorators.idempotent_id('028eb864-59e9-4ed6-a062-9d5de9eba652')
|
||||
def test_network_interface_attribute_description(self):
|
||||
desc = data_utils.rand_name('ni')
|
||||
data = self.client.create_network_interface(
|
||||
SubnetId=self.subnet_id, Description=desc)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
data = self.client.describe_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Attribute='description')
|
||||
self.assertEqual(desc, data['Description']['Value'])
|
||||
|
||||
new_desc = data_utils.rand_name('new-ni')
|
||||
self.client.modify_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Description={'Value': new_desc})
|
||||
|
||||
data = self.client.describe_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Attribute='description')
|
||||
self.assertEqual(new_desc, data['Description']['Value'])
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
@decorators.idempotent_id('9428b5e6-42f2-495f-a535-df53d1fcf4af')
|
||||
def test_network_interface_attribute_source_dest_check(self):
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
self.client.modify_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, SourceDestCheck={'Value': False})
|
||||
|
||||
data = self.client.describe_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Attribute='sourceDestCheck')
|
||||
self.assertFalse(data['SourceDestCheck']['Value'])
|
||||
|
||||
# NOTE(andrey-mp): ResetNetworkInterfaceAttribute had inadequate json
|
||||
# scheme in botocore and doesn't work against Amazon.
|
||||
|
||||
self.client.modify_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, SourceDestCheck={'Value': True})
|
||||
|
||||
data = self.client.describe_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Attribute='sourceDestCheck')
|
||||
self.assertEqual(True, data['SourceDestCheck']['Value'])
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
@decorators.idempotent_id('19d25f59-5b32-4314-b4da-7c8f679b7a96')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_network_interface_attribute_attachment(self):
|
||||
instance_id = self.run_instance(SubnetId=self.subnet_id)
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
nis = instance.get('NetworkInterfaces', [])
|
||||
self.assertEqual(1, len(nis))
|
||||
self.assertTrue(nis[0]['Attachment']['DeleteOnTermination'])
|
||||
ni_id = nis[0]['NetworkInterfaceId']
|
||||
|
||||
data = self.client.describe_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Attribute='attachment')
|
||||
self.assertIn('Attachment', data)
|
||||
self.assertTrue(data['Attachment'].get('AttachmentId'))
|
||||
self.assertTrue(data['Attachment'].get('DeleteOnTermination'))
|
||||
self.assertEqual(0, data['Attachment'].get('DeviceIndex'))
|
||||
self.assertEqual(instance_id, data['Attachment'].get('InstanceId'))
|
||||
self.assertEqual('attached', data['Attachment'].get('Status'))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('74967cd0-155f-4cfe-994e-2c6803dad04c')
|
||||
def test_network_interface_attribute_empty_attachment(self):
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
data = self.client.describe_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Attribute='attachment')
|
||||
self.assertNotIn('Attachment', data)
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
@decorators.idempotent_id('a55f1169-d302-4166-b74e-e84a0d79129c')
|
||||
def test_network_interface_attribute_group_set(self):
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
data = self.client.describe_network_interface_attribute(
|
||||
NetworkInterfaceId=ni_id, Attribute='groupSet')
|
||||
self.assertIn('Groups', data)
|
||||
self.assertEqual(1, len(data['Groups']))
|
||||
self.assertEqual('default', data['Groups'][0]['GroupName'])
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
@decorators.idempotent_id('7832976f-27cb-405e-ab05-466b102d86f8')
|
||||
def test_instance_attributes_negative(self):
|
||||
data = self.client.create_network_interface(SubnetId=self.subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.describe_network_interface_attribute,
|
||||
NetworkInterfaceId=ni_id)
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_network_interface_attribute,
|
||||
NetworkInterfaceId=ni_id, Attribute='fake')
|
||||
self.assertRaises('InvalidNetworkInterfaceID.NotFound',
|
||||
self.client.describe_network_interface_attribute,
|
||||
NetworkInterfaceId='eni-0', Attribute='description')
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_network_interface_attribute,
|
||||
NetworkInterfaceId=ni_id)
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.modify_network_interface_attribute,
|
||||
NetworkInterfaceId=ni_id,
|
||||
Attachment={'AttachmentId': 'fake'})
|
||||
self.assertRaises('InvalidAttachmentID.NotFound',
|
||||
self.client.modify_network_interface_attribute,
|
||||
NetworkInterfaceId=ni_id,
|
||||
Attachment={'AttachmentId': 'eni-attach-0',
|
||||
'DeleteOnTermination': True})
|
||||
self.assertRaises('InvalidGroup.NotFound',
|
||||
self.client.modify_network_interface_attribute,
|
||||
NetworkInterfaceId=ni_id, Groups=['sg-0'])
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.modify_network_interface_attribute,
|
||||
NetworkInterfaceId=ni_id, Description={})
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
|
@ -1,47 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class RegionTest(base.EC2TestCase):
|
||||
|
||||
@decorators.idempotent_id('f303e87e-4e5f-4110-a5da-5f690acb44ba')
|
||||
def test_describe_regions(self):
|
||||
data = self.client.describe_regions()
|
||||
self.assertNotEmpty(data['Regions'])
|
||||
|
||||
region = CONF.aws.aws_region
|
||||
if not region:
|
||||
return
|
||||
|
||||
regions = [r['RegionName'] for r in data['Regions']]
|
||||
self.assertIn(region, regions)
|
||||
|
||||
@decorators.idempotent_id('be38f383-4637-4581-bb62-b47c1463f0a1')
|
||||
def test_describe_zones(self):
|
||||
data = self.client.describe_availability_zones()
|
||||
self.assertNotEmpty(data['AvailabilityZones'])
|
||||
|
||||
region = CONF.aws.aws_region
|
||||
if not region:
|
||||
return
|
||||
|
||||
# TODO(andrey-mp): add checking of other fields of returned data
|
|
@ -1,338 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class RouteTest(base.EC2TestCase):
|
||||
|
||||
VPC_CIDR = '10.14.0.0/20'
|
||||
SUBNET_CIDR = '10.14.0.0/24'
|
||||
vpc_id = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(RouteTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR)
|
||||
cls.vpc_id = data['Vpc']['VpcId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc, VpcId=cls.vpc_id)
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id)
|
||||
|
||||
@decorators.idempotent_id('69c04d14-5603-4a98-9331-739821b98b10')
|
||||
def test_create_delete_route_table(self):
|
||||
data = self.client.create_route_table(VpcId=self.vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
rt = data['RouteTable']
|
||||
self.assertEqual(self.vpc_id, rt['VpcId'])
|
||||
self.assertEqual(1, len(rt['Routes']))
|
||||
route = rt['Routes'][0]
|
||||
self.assertEqual(self.VPC_CIDR, route['DestinationCidrBlock'])
|
||||
self.assertEqual('active', route['State'])
|
||||
|
||||
data = self.client.delete_route_table(RouteTableId=rt_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
self.assertRaises('InvalidRouteTableID.NotFound',
|
||||
self.client.describe_route_tables,
|
||||
RouteTableIds=[rt_id])
|
||||
|
||||
self.assertRaises('InvalidRouteTableID.NotFound',
|
||||
self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
@decorators.idempotent_id('d8051b30-eb70-4c4b-988b-56078a125af3')
|
||||
def test_describe_route_tables_base(self):
|
||||
data = self.client.create_route_table(VpcId=self.vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
# NOTE(andrey-mp): by real id
|
||||
data = self.client.describe_route_tables(RouteTableIds=[rt_id])
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
|
||||
# NOTE(andrey-mp): by fake id
|
||||
self.assertRaises('InvalidRouteTableID.NotFound',
|
||||
self.client.describe_route_tables,
|
||||
RouteTableIds=['rtb-0'])
|
||||
|
||||
data = self.client.delete_route_table(RouteTableId=rt_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('77a53f3e-437a-45ed-b3b5-e6b7ab2c9407')
|
||||
def test_describe_route_tables_filters(self):
|
||||
data = self.client.create_route_table(VpcId=self.vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id,
|
||||
CidrBlock=self.SUBNET_CIDR)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
data = self.client.associate_route_table(RouteTableId=rt_id,
|
||||
SubnetId=subnet_id)
|
||||
assoc_id = data['AssociationId']
|
||||
self.addResourceCleanUp(self.client.disassociate_route_table,
|
||||
AssociationId=assoc_id)
|
||||
|
||||
# NOTE(andrey-mp): by association_id
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'association.route-table-association-id',
|
||||
'Values': [assoc_id]}])
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
|
||||
# NOTE(andrey-mp): by route table id
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'association.route-table-id',
|
||||
'Values': [rt_id]}])
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
|
||||
# NOTE(andrey-mp): by subnet id
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'association.subnet-id',
|
||||
'Values': [subnet_id]}])
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
|
||||
# NOTE(andrey-mp): by filter real vpc
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [self.vpc_id]}])
|
||||
self.assertLess(0, len(data['RouteTables']))
|
||||
|
||||
# NOTE(andrey-mp): by filter fake vpc
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': ['vpc-0']}])
|
||||
self.assertEqual(0, len(data['RouteTables']))
|
||||
|
||||
# NOTE(andrey-mp): by fake filter
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_route_tables,
|
||||
Filters=[{'Name': 'fake', 'Values': ['fake']}])
|
||||
|
||||
@decorators.idempotent_id('55361f57-331a-43b8-8729-efee2d1c0dc9')
|
||||
def test_associate_disassociate_route_table(self):
|
||||
data = self.client.create_route_table(VpcId=self.vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
res_clean_rt = self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id,
|
||||
CidrBlock=self.SUBNET_CIDR)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean_subnet = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
data = self.client.associate_route_table(RouteTableId=rt_id,
|
||||
SubnetId=subnet_id)
|
||||
assoc_id = data['AssociationId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.disassociate_route_table, AssociationId=assoc_id)
|
||||
|
||||
data = self.client.disassociate_route_table(AssociationId=assoc_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean_subnet)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
data = self.client.delete_route_table(RouteTableId=rt_id)
|
||||
self.cancelResourceCleanUp(res_clean_rt)
|
||||
|
||||
@decorators.idempotent_id('b1a07211-6e9a-41db-8017-47e7c4b9c043')
|
||||
def test_replace_route_table(self):
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id,
|
||||
CidrBlock=self.SUBNET_CIDR)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean_subnet = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
# NOTE(andrey-mp): by vpc id
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [self.vpc_id]}])
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
self.assertEqual(1, len(data['RouteTables'][0]['Associations']))
|
||||
default_rt_id = data['RouteTables'][0]['RouteTableId']
|
||||
main_assoc = data['RouteTables'][0]['Associations'][0]
|
||||
self.assertTrue(main_assoc['Main'])
|
||||
main_assoc_id = main_assoc['RouteTableAssociationId']
|
||||
|
||||
data = self.client.create_route_table(VpcId=self.vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
res_clean_rt = self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
data = self.client.replace_route_table_association(
|
||||
RouteTableId=rt_id, AssociationId=main_assoc_id)
|
||||
assoc_id = data['NewAssociationId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.replace_route_table_association,
|
||||
RouteTableId=default_rt_id,
|
||||
AssociationId=assoc_id)
|
||||
|
||||
# NOTE(andrey-mp): by vpc id
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [self.vpc_id]}])
|
||||
self.assertEqual(2, len(data['RouteTables']))
|
||||
for rt in data['RouteTables']:
|
||||
if rt['RouteTableId'] == rt_id:
|
||||
self.assertEqual(1, len(rt['Associations']))
|
||||
self.assertTrue(rt['Associations'][0]['Main'])
|
||||
else:
|
||||
self.assertEmpty(rt.get('Associations', []))
|
||||
|
||||
self.assertRaises('DependencyViolation',
|
||||
self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.disassociate_route_table,
|
||||
AssociationId=assoc_id)
|
||||
|
||||
data = self.client.replace_route_table_association(
|
||||
RouteTableId=default_rt_id,
|
||||
AssociationId=assoc_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
data = self.client.delete_route_table(RouteTableId=rt_id)
|
||||
self.cancelResourceCleanUp(res_clean_rt)
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean_subnet)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
@decorators.idempotent_id('c112ecdb-dce3-4497-b11b-5349a2d89336')
|
||||
def test_create_delete_route(self):
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id,
|
||||
CidrBlock=self.SUBNET_CIDR)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean_subnet = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
kwargs = {
|
||||
'SubnetId': subnet_id,
|
||||
}
|
||||
data = self.client.create_network_interface(*[], **kwargs)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean_ni = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id)
|
||||
|
||||
data = self.client.create_route_table(VpcId=self.vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
res_clean_rt = self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': self.VPC_CIDR,
|
||||
'RouteTableId': rt_id,
|
||||
'NetworkInterfaceId': ni_id
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.create_route,
|
||||
**kwargs)
|
||||
|
||||
# can create wider route
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': '10.14.0.0/19',
|
||||
'RouteTableId': rt_id,
|
||||
'NetworkInterfaceId': ni_id
|
||||
}
|
||||
data = self.client.create_route(*[], **kwargs)
|
||||
# can create to another vpc
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': '10.15.0.0/20',
|
||||
'RouteTableId': rt_id,
|
||||
'NetworkInterfaceId': ni_id
|
||||
}
|
||||
data = self.client.create_route(*[], **kwargs)
|
||||
|
||||
data = self.client.describe_route_tables(RouteTableIds=[rt_id])
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
self.assertEqual(3, len(data['RouteTables'][0]['Routes']))
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': '10.15.0.0/24',
|
||||
'RouteTableId': rt_id,
|
||||
}
|
||||
self.assertRaises('InvalidRoute.NotFound',
|
||||
self.client.delete_route,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': self.VPC_CIDR,
|
||||
'RouteTableId': rt_id,
|
||||
}
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.delete_route,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': self.SUBNET_CIDR,
|
||||
'RouteTableId': rt_id,
|
||||
}
|
||||
self.assertRaises('InvalidRoute.NotFound',
|
||||
self.client.delete_route,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': '10.16.0.0/24',
|
||||
'RouteTableId': rt_id,
|
||||
}
|
||||
self.assertRaises('InvalidRoute.NotFound',
|
||||
self.client.delete_route,
|
||||
**kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': '10.15.0.0/20',
|
||||
'RouteTableId': rt_id,
|
||||
}
|
||||
data = self.client.delete_route(*[], **kwargs)
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': '10.14.0.0/19',
|
||||
'RouteTableId': rt_id,
|
||||
}
|
||||
data = self.client.delete_route(*[], **kwargs)
|
||||
|
||||
data = self.client.delete_route_table(RouteTableId=rt_id)
|
||||
self.cancelResourceCleanUp(res_clean_rt)
|
||||
|
||||
data = self.client.delete_network_interface(
|
||||
NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean_ni)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean_subnet)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
|
@ -1,324 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class SecurityGroupBaseTest(base.EC2TestCase):
|
||||
|
||||
def _test_rules(self, add_func, del_func, field, vpc_id=None):
|
||||
kwargs = dict()
|
||||
if vpc_id:
|
||||
kwargs['Filters'] = [{'Name': 'vpc-id', 'Values': [vpc_id]}]
|
||||
data = self.client.describe_security_groups(*[], **kwargs)
|
||||
security_groups = data['SecurityGroups']
|
||||
if not vpc_id:
|
||||
# TODO(andrey-mp): remove it when fitering by None will be
|
||||
security_groups = [sg for sg in security_groups
|
||||
if sg.get('VpcId') is None]
|
||||
default_group = security_groups[0]
|
||||
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
kwargs = {'GroupName': name, 'Description': desc}
|
||||
if vpc_id:
|
||||
kwargs['VpcId'] = vpc_id
|
||||
data = self.client.create_security_group(*[], **kwargs)
|
||||
group_id = data['GroupId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
data = self.client.describe_security_groups(GroupIds=[group_id])
|
||||
count = len(data['SecurityGroups'][0][field])
|
||||
|
||||
kwargs = {
|
||||
'GroupId': group_id,
|
||||
'IpPermissions': [{
|
||||
'IpProtocol': 'icmp',
|
||||
'FromPort': -1,
|
||||
'ToPort': -1,
|
||||
'IpRanges': [{
|
||||
'CidrIp': '10.0.0.0/8'
|
||||
}],
|
||||
}, {
|
||||
'UserIdGroupPairs': [{'GroupId': default_group['GroupId']}],
|
||||
'ToPort': 65535,
|
||||
'IpProtocol': 'tcp',
|
||||
'FromPort': 1
|
||||
}]
|
||||
}
|
||||
add_func(*[], **kwargs)
|
||||
|
||||
data = self.client.describe_security_groups(GroupIds=[group_id])
|
||||
self.assertEqual(1, len(data['SecurityGroups']))
|
||||
self.assertEqual(count + 2, len(data['SecurityGroups'][0][field]))
|
||||
found = 0
|
||||
for perm in data['SecurityGroups'][0][field]:
|
||||
cidrs = [v['CidrIp'] for v in perm.get('IpRanges', [])]
|
||||
if (perm.get('FromPort') == -1 and
|
||||
perm.get('ToPort') == -1 and
|
||||
perm.get('IpProtocol') == 'icmp' and
|
||||
len(perm.get('IpRanges')) == 1 and
|
||||
'10.0.0.0/8' in cidrs):
|
||||
found = found + 1
|
||||
elif (perm.get('FromPort') == 1 and
|
||||
perm.get('ToPort') == 65535 and
|
||||
perm.get('IpProtocol') == 'tcp' and
|
||||
len(perm.get('UserIdGroupPairs')) == 1 and
|
||||
perm.get('UserIdGroupPairs')[0]['GroupId']
|
||||
== default_group['GroupId']):
|
||||
found = found + 1
|
||||
self.assertEqual(2, found)
|
||||
|
||||
del_func(*[], **kwargs)
|
||||
|
||||
data = self.client.describe_security_groups(GroupIds=[group_id])
|
||||
self.assertEqual(1, len(data['SecurityGroups']))
|
||||
self.assertEqual(count, len(data['SecurityGroups'][0][field]))
|
||||
|
||||
if vpc_id:
|
||||
self.assertRaises('InvalidPermission.NotFound', del_func, **kwargs)
|
||||
else:
|
||||
del_func(*[], **kwargs)
|
||||
|
||||
self.client.delete_security_group(GroupId=group_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
|
||||
class SecurityGroupInVPCTest(SecurityGroupBaseTest):
|
||||
|
||||
VPC_CIDR = '10.10.0.0/20'
|
||||
vpc_id = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(SecurityGroupInVPCTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR)
|
||||
cls.vpc_id = data['Vpc']['VpcId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc, VpcId=cls.vpc_id)
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id)
|
||||
|
||||
@decorators.idempotent_id('f8354908-1b3a-4e7b-89e3-6956850bbbfb')
|
||||
def test_create_delete_security_group(self):
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(VpcId=self.vpc_id,
|
||||
GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
|
||||
self.client.delete_security_group(GroupId=group_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
self.assertRaises('InvalidGroup.NotFound',
|
||||
self.client.describe_security_groups,
|
||||
GroupIds=[group_id])
|
||||
|
||||
self.assertRaises('InvalidGroup.NotFound',
|
||||
self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
|
||||
@decorators.idempotent_id('fe209503-c348-4456-94b4-a77e68fabcbb')
|
||||
def test_create_duplicate_security_group(self):
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(VpcId=self.vpc_id,
|
||||
GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
|
||||
self.assertRaises('InvalidGroup.Duplicate',
|
||||
self.client.create_security_group,
|
||||
VpcId=self.vpc_id, GroupName=name, Description=desc)
|
||||
|
||||
data = self.client.delete_security_group(GroupId=group_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('ffe5084a-2d05-42d1-ae8d-edcb0af27909')
|
||||
def test_create_duplicate_security_group_in_another_vpc(self):
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(VpcId=self.vpc_id,
|
||||
GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
|
||||
data = self.client.create_vpc(CidrBlock=self.VPC_CIDR)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
|
||||
data = self.client.create_security_group(VpcId=vpc_id,
|
||||
GroupName=name,
|
||||
Description=desc)
|
||||
time.sleep(2)
|
||||
self.client.delete_security_group(GroupId=data['GroupId'])
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
data = self.client.delete_security_group(GroupId=group_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('524993f7-a8d3-4ffc-bbf1-6a3014377181')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"MismatchError: 'InvalidParameterValue' != 'ValidationError'")
|
||||
def test_create_invalid_name_desc(self):
|
||||
valid = data_utils.rand_name('sgName')
|
||||
invalid = 'name%"'
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.create_security_group,
|
||||
VpcId=self.vpc_id, GroupName=invalid,
|
||||
Description=valid)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.create_security_group,
|
||||
VpcId=self.vpc_id, GroupName=valid,
|
||||
Description=invalid)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.create_security_group,
|
||||
VpcId=self.vpc_id, GroupName='default',
|
||||
Description='default')
|
||||
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.create_security_group,
|
||||
VpcId=self.vpc_id, GroupName=valid, Description='')
|
||||
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.create_security_group,
|
||||
VpcId=self.vpc_id, GroupName='', Description=valid)
|
||||
|
||||
@decorators.idempotent_id('3460cefd-c759-4738-ba75-b275939aad1d')
|
||||
def test_ingress_rules(self):
|
||||
self._test_rules(self.client.authorize_security_group_ingress,
|
||||
self.client.revoke_security_group_ingress,
|
||||
'IpPermissions', self.vpc_id)
|
||||
|
||||
@decorators.idempotent_id('74a5de83-69b4-4cc5-9431-e4c1f691f0c1')
|
||||
def test_egress_rules(self):
|
||||
self._test_rules(self.client.authorize_security_group_egress,
|
||||
self.client.revoke_security_group_egress,
|
||||
'IpPermissionsEgress', self.vpc_id)
|
||||
|
||||
|
||||
class SecurityGroupEC2ClassicTest(SecurityGroupBaseTest):
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(SecurityGroupEC2ClassicTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_ec2_enabled():
|
||||
raise cls.skipException('EC2-classic is disabled')
|
||||
|
||||
@decorators.idempotent_id('eb097f7c-4b10-4365-aa34-c17e5769f4a7')
|
||||
def test_create_delete_security_group(self):
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
|
||||
data = self.client.describe_security_groups(GroupNames=[name])
|
||||
self.assertEqual(1, len(data['SecurityGroups']))
|
||||
self.assertEqual(group_id, data['SecurityGroups'][0]['GroupId'])
|
||||
|
||||
data = self.client.describe_security_groups(GroupIds=[group_id])
|
||||
self.assertEqual(1, len(data['SecurityGroups']))
|
||||
self.assertEqual(name, data['SecurityGroups'][0]['GroupName'])
|
||||
|
||||
self.client.delete_security_group(GroupName=name)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('b97b8b4a-811e-4584-8e79-086499459aca')
|
||||
def test_create_duplicate_security_group(self):
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
|
||||
self.assertRaises('InvalidGroup.Duplicate',
|
||||
self.client.create_security_group,
|
||||
GroupName=name, Description=desc)
|
||||
|
||||
self.client.delete_security_group(GroupId=group_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('b80c578d-0c0d-4c7e-b0ee-a7ed23b6b209')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"MismatchError: 'MissingParameter' != 'ValidationError'")
|
||||
def test_create_invalid_name_desc(self):
|
||||
valid = data_utils.rand_name('sgName')
|
||||
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.create_security_group,
|
||||
GroupName=valid, Description='')
|
||||
|
||||
self.assertRaises('MissingParameter',
|
||||
self.client.create_security_group,
|
||||
GroupName='', Description=valid)
|
||||
|
||||
self.assertRaises('InvalidGroup.Reserved',
|
||||
self.client.create_security_group,
|
||||
GroupName='default', Description='default')
|
||||
|
||||
@decorators.idempotent_id('eba8a7c4-3781-4562-b137-dbe8037395a3')
|
||||
def test_ingress_rules(self):
|
||||
self._test_rules(self.client.authorize_security_group_ingress,
|
||||
self.client.revoke_security_group_ingress,
|
||||
'IpPermissions')
|
||||
|
||||
@decorators.idempotent_id('435d5e53-060f-455a-9317-60177246e04d')
|
||||
def test_egress_rules(self):
|
||||
def _test():
|
||||
self._test_rules(
|
||||
self.client.authorize_security_group_egress,
|
||||
self.client.revoke_security_group_egress,
|
||||
'IpPermissionsEgress')
|
||||
|
||||
self.assertRaises('InvalidParameterValue', _test)
|
|
@ -1,267 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class SnapshotTest(base.EC2TestCase):
|
||||
|
||||
@decorators.idempotent_id('3eb8868b-5c6b-4619-8c99-9429ca86a526')
|
||||
def test_create_delete_snapshot(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_vol = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
desc = 'test snapshot'
|
||||
kwargs = {
|
||||
'VolumeId': volume_id,
|
||||
'Description': desc
|
||||
}
|
||||
data = self.client.create_snapshot(*[], **kwargs)
|
||||
snapshot_id = data['SnapshotId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
self.assertEqual(desc, data['Description'])
|
||||
self.assertEqual(volume_id, data['VolumeId'])
|
||||
self.assertEqual(1, data['VolumeSize'])
|
||||
self.assertNotEmpty(data.get('State', ''))
|
||||
if 'Encrypted' in data:
|
||||
self.assertFalse(data['Encrypted'])
|
||||
self.assertIsNotNone(data['StartTime'])
|
||||
|
||||
data = self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_snapshot_waiter().wait_delete(snapshot_id)
|
||||
|
||||
data = self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_vol)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
@decorators.idempotent_id('dfe0f2e6-c103-4e26-93e5-63010bf6b0af')
|
||||
def test_describe_snapshots(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_vol = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
desc = 'test snapshot'
|
||||
kwargs = {
|
||||
'VolumeId': volume_id,
|
||||
'Description': desc
|
||||
}
|
||||
data = self.client.create_snapshot(*[], **kwargs)
|
||||
snapshot_id = data['SnapshotId']
|
||||
ownerId = data['OwnerId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
self.assertEqual(desc, data['Description'])
|
||||
self.assertEqual(volume_id, data['VolumeId'])
|
||||
self.assertEqual(1, data['VolumeSize'])
|
||||
self.assertNotEmpty(data.get('State', ''))
|
||||
if 'Encrypted' in data:
|
||||
self.assertFalse(data['Encrypted'])
|
||||
self.assertIsNotNone(data['StartTime'])
|
||||
|
||||
data = self.client.describe_snapshots(SnapshotIds=[snapshot_id])
|
||||
self.assertEqual(1, len(data['Snapshots']))
|
||||
data = data['Snapshots'][0]
|
||||
self.assertEqual(snapshot_id, data['SnapshotId'])
|
||||
self.assertEqual(desc, data['Description'])
|
||||
self.assertEqual(volume_id, data['VolumeId'])
|
||||
self.assertEqual(1, data['VolumeSize'])
|
||||
self.assertNotEmpty(data.get('State', ''))
|
||||
if 'Encrypted' in data:
|
||||
self.assertFalse(data['Encrypted'])
|
||||
self.assertIsNotNone(data['StartTime'])
|
||||
|
||||
data = self.client.describe_snapshots(OwnerIds=[ownerId])
|
||||
data = [s for s in data['Snapshots'] if s['SnapshotId'] == snapshot_id]
|
||||
self.assertEqual(1, len(data))
|
||||
|
||||
data = self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_snapshot_waiter().wait_delete(snapshot_id)
|
||||
|
||||
self.assertRaises('InvalidSnapshot.NotFound',
|
||||
self.client.describe_snapshots,
|
||||
SnapshotIds=[snapshot_id])
|
||||
|
||||
data = self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_vol)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
@decorators.idempotent_id('c4a99068-3c9e-4d8c-8d7a-e96548cfdaa7')
|
||||
def test_create_volume_from_snapshot(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_vol = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
vol1 = data
|
||||
|
||||
desc = 'test snapshot'
|
||||
kwargs = {
|
||||
'VolumeId': volume_id,
|
||||
'Description': desc
|
||||
}
|
||||
data = self.client.create_snapshot(*[], **kwargs)
|
||||
snapshot_id = data['SnapshotId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
kwargs = {
|
||||
'SnapshotId': snapshot_id,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id2 = data['VolumeId']
|
||||
clean_vol2 = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id2)
|
||||
self.get_volume_waiter().wait_available(volume_id2)
|
||||
|
||||
self.assertNotEqual(volume_id, volume_id2)
|
||||
self.assertEqual(vol1['Size'], data['Size'])
|
||||
self.assertEqual(snapshot_id, data['SnapshotId'])
|
||||
|
||||
data = self.client.describe_volumes(
|
||||
Filters=[{'Name': 'snapshot-id', 'Values': [snapshot_id]}])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
self.assertEqual(volume_id2, data['Volumes'][0]['VolumeId'])
|
||||
|
||||
data = self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_snapshot_waiter().wait_delete(snapshot_id)
|
||||
|
||||
data = self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_vol)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
data = self.client.delete_volume(VolumeId=volume_id2)
|
||||
self.cancelResourceCleanUp(clean_vol2)
|
||||
self.get_volume_waiter().wait_delete(volume_id2)
|
||||
|
||||
@decorators.idempotent_id('c6f0be0a-67ca-4f33-b821-83e9158cee66')
|
||||
def test_create_increased_volume_from_snapshot(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_vol = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
desc = 'test snapshot'
|
||||
kwargs = {
|
||||
'VolumeId': volume_id,
|
||||
'Description': desc
|
||||
}
|
||||
data = self.client.create_snapshot(*[], **kwargs)
|
||||
snapshot_id = data['SnapshotId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
kwargs = {
|
||||
'Size': 2,
|
||||
'SnapshotId': snapshot_id,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id2 = data['VolumeId']
|
||||
clean_vol2 = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id2)
|
||||
self.get_volume_waiter().wait_available(volume_id2)
|
||||
|
||||
self.assertNotEqual(volume_id, volume_id2)
|
||||
self.assertEqual(2, data['Size'])
|
||||
self.assertEqual(snapshot_id, data['SnapshotId'])
|
||||
|
||||
data = self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_snapshot_waiter().wait_delete(snapshot_id)
|
||||
|
||||
data = self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_vol)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
data = self.client.delete_volume(VolumeId=volume_id2)
|
||||
self.cancelResourceCleanUp(clean_vol2)
|
||||
self.get_volume_waiter().wait_delete(volume_id2)
|
||||
|
||||
@decorators.idempotent_id('8f885da3-97e3-419e-b382-036ca7b25877')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Openstack can't delete volume with snapshots")
|
||||
def test_delete_volume_with_snapshots(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_vol = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
desc = 'test snapshot'
|
||||
kwargs = {
|
||||
'VolumeId': volume_id,
|
||||
'Description': desc
|
||||
}
|
||||
data = self.client.create_snapshot(*[], **kwargs)
|
||||
snapshot_id = data['SnapshotId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
data = self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_vol)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
data = self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_snapshot_waiter().wait_delete(snapshot_id)
|
|
@ -1,191 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class SubnetTest(base.EC2TestCase):
|
||||
|
||||
BASE_CIDR = '10.2.0.0'
|
||||
VPC_CIDR = BASE_CIDR + '/20'
|
||||
vpc_id = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(SubnetTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR)
|
||||
cls.vpc_id = data['Vpc']['VpcId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc, VpcId=cls.vpc_id)
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id)
|
||||
|
||||
@decorators.idempotent_id('506993c3-aff6-48ea-8916-da8a4f199a66')
|
||||
def test_create_delete_subnet(self):
|
||||
cidr = self.BASE_CIDR + '/24'
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id,
|
||||
CidrBlock=cidr)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.assertEqual(cidr, data['Subnet']['CidrBlock'])
|
||||
self.assertIsNotNone(data['Subnet'].get('AvailableIpAddressCount'))
|
||||
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
self.assertRaises('InvalidSubnetID.NotFound',
|
||||
self.client.describe_subnets,
|
||||
SubnetIds=[subnet_id])
|
||||
|
||||
self.assertRaises('InvalidSubnetID.NotFound',
|
||||
self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
|
||||
@decorators.idempotent_id('4d27f078-46d2-4e2c-87c4-b5ba4589c2aa')
|
||||
def test_dependency_subnet_to_vpc(self):
|
||||
data = self.client.create_vpc(CidrBlock=self.VPC_CIDR)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
vpc_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
cidr = self.BASE_CIDR + '/24'
|
||||
data = self.client.create_subnet(VpcId=vpc_id, CidrBlock=cidr)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
self.assertRaises('DependencyViolation',
|
||||
self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(vpc_clean)
|
||||
|
||||
@decorators.idempotent_id('85ee17ca-5e2c-4d54-84ca-efcca8f94ff9')
|
||||
@testtools.skipUnless(
|
||||
CONF.aws.run_incompatible_tests,
|
||||
"bug with overlapped subnets")
|
||||
def test_create_overlapped_subnet(self):
|
||||
cidr = self.BASE_CIDR + '/24'
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id, CidrBlock=cidr)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
cidr = '10.2.0.128/26'
|
||||
|
||||
def _rollback(fn_data):
|
||||
self.client.delete_subnet(SubnetId=data['Subnet']['SubnetId'])
|
||||
self.assertRaises('InvalidSubnet.Conflict',
|
||||
self.client.create_subnet, rollback_fn=_rollback,
|
||||
VpcId=self.vpc_id, CidrBlock=cidr)
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
@decorators.idempotent_id('20ea7ea4-67e6-42ed-9b91-e7b4b8d82605')
|
||||
def test_create_subnet_invalid_cidr(self):
|
||||
def _rollback(fn_data):
|
||||
self.client.delete_subnet(SubnetId=fn_data['Subnet']['SubnetId'])
|
||||
|
||||
# NOTE(andrey-mp): another cidr than VPC has
|
||||
cidr = '10.1.0.0/24'
|
||||
self.assertRaises('InvalidSubnet.Range',
|
||||
self.client.create_subnet, rollback_fn=_rollback,
|
||||
VpcId=self.vpc_id, CidrBlock=cidr)
|
||||
|
||||
# NOTE(andrey-mp): bigger cidr than VPC has
|
||||
cidr = self.BASE_CIDR + '/19'
|
||||
self.assertRaises('InvalidSubnet.Range',
|
||||
self.client.create_subnet, rollback_fn=_rollback,
|
||||
VpcId=self.vpc_id, CidrBlock=cidr)
|
||||
|
||||
# NOTE(andrey-mp): too small cidr
|
||||
cidr = self.BASE_CIDR + '/29'
|
||||
self.assertRaises('InvalidSubnet.Range',
|
||||
self.client.create_subnet, rollback_fn=_rollback,
|
||||
VpcId=self.vpc_id, CidrBlock=cidr)
|
||||
|
||||
@decorators.idempotent_id('8f0f2637-118f-4307-8585-7470808b3a86')
|
||||
def test_describe_subnets_base(self):
|
||||
cidr = self.BASE_CIDR + '/24'
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id, CidrBlock=cidr)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
# NOTE(andrey-mp): by real id
|
||||
data = self.client.describe_subnets(SubnetIds=[subnet_id])
|
||||
self.assertEqual(1, len(data['Subnets']))
|
||||
|
||||
# NOTE(andrey-mp): by fake id
|
||||
self.assertRaises('InvalidSubnetID.NotFound',
|
||||
self.client.describe_subnets,
|
||||
SubnetIds=['subnet-0'])
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
@decorators.idempotent_id('182d151c-2dca-46bd-b137-1dece7276e1f')
|
||||
def test_describe_subnets_filters(self):
|
||||
cidr = self.BASE_CIDR + '/24'
|
||||
data = self.client.create_subnet(VpcId=self.vpc_id, CidrBlock=cidr)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
self.get_subnet_waiter().wait_available(subnet_id)
|
||||
|
||||
# NOTE(andrey-mp): by filter real cidr
|
||||
data = self.client.describe_subnets(
|
||||
Filters=[{'Name': 'cidr', 'Values': [cidr]}])
|
||||
self.assertEqual(1, len(data['Subnets']))
|
||||
|
||||
# NOTE(andrey-mp): by filter fake cidr
|
||||
data = self.client.describe_subnets(
|
||||
Filters=[{'Name': 'cidr', 'Values': ['123.0.0.0/16']}])
|
||||
self.assertEqual(0, len(data['Subnets']))
|
||||
|
||||
# NOTE(andrey-mp): by fake filter
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_subnets,
|
||||
Filters=[{'Name': 'fake', 'Values': ['fake']}])
|
||||
|
||||
data = self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
|
@ -1,509 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class TagTest(base.EC2TestCase):
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(TagTest, cls).setUpClass()
|
||||
|
||||
cls.zone = CONF.aws.aws_zone
|
||||
data = cls.client.create_volume(
|
||||
Size=1, AvailabilityZone=cls.zone)
|
||||
cls.volume_id = data['VolumeId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_volume,
|
||||
VolumeId=cls.volume_id)
|
||||
cls.get_volume_waiter().wait_available(cls.volume_id)
|
||||
|
||||
@decorators.idempotent_id('249f59cf-2fcd-47ac-a233-682f17fc3129')
|
||||
def test_create_get_delete_tag(self):
|
||||
tag_key = data_utils.rand_name('tag-key')
|
||||
self.client.create_tags(Resources=[self.volume_id],
|
||||
Tags=[{'Key': tag_key, 'Value': 'fake_value'}])
|
||||
self.addResourceCleanUp(self.client.delete_tags,
|
||||
Resources=[self.volume_id],
|
||||
Tags=[{'Key': tag_key}])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [self.volume_id]}])
|
||||
self.assertEqual(1, len(data['Tags']))
|
||||
|
||||
self.client.delete_tags(Resources=[self.volume_id],
|
||||
Tags=[{'Key': tag_key}])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [self.volume_id]}])
|
||||
self.assertEqual(0, len(data['Tags']))
|
||||
|
||||
@decorators.idempotent_id('41dec90b-a878-4367-ba95-83757281e343')
|
||||
def test_describe_tags(self):
|
||||
tag_key = data_utils.rand_name('tag-key')
|
||||
self.client.create_tags(Resources=[self.volume_id],
|
||||
Tags=[{'Key': tag_key, 'Value': 'fake_value'}])
|
||||
self.addResourceCleanUp(self.client.delete_tags,
|
||||
Resources=[self.volume_id],
|
||||
Tags=[{'Key': tag_key}])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [self.volume_id]}])
|
||||
self.assertEqual(1, len(data['Tags']))
|
||||
tag = data['Tags'][0]
|
||||
self.assertEqual('volume', tag.get('ResourceType'))
|
||||
self.assertEqual(self.volume_id, tag.get('ResourceId'))
|
||||
self.assertEqual(tag_key, tag.get('Key'))
|
||||
self.assertEqual('fake_value', tag.get('Value'))
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [self.volume_id]},
|
||||
{'Name': 'key', 'Values': [tag_key]}])
|
||||
self.assertEqual(1, len(data['Tags']))
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'key', 'Values': [tag_key]}])
|
||||
self.assertIn(tag_key, [k.get('Key') for k in data['Tags']])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'value', 'Values': ['fake_value']}])
|
||||
self.assertIn('fake_value', [k.get('Value') for k in data['Tags']])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'key', 'Values': ['fake_value']}])
|
||||
items = [k.get('Key') for k in data['Tags']]
|
||||
self.assertNotIn(tag_key, items)
|
||||
self.assertNotIn('fake_value', items)
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-type', 'Values': ['volume']}])
|
||||
self.assertIn(tag_key, [k.get('Key') for k in data['Tags']])
|
||||
|
||||
self.client.delete_tags(Resources=[self.volume_id],
|
||||
Tags=[{'Key': tag_key}])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [self.volume_id]}])
|
||||
self.assertEqual(0, len(data['Tags']))
|
||||
|
||||
def _test_tag_resource(self, resource_id, res_type, describe_func):
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [resource_id]}])
|
||||
origin_count = len(data['Tags'])
|
||||
|
||||
tag_key = data_utils.rand_name('tag-key')
|
||||
data = self.client.create_tags(Resources=[resource_id],
|
||||
Tags=[{'Key': tag_key, 'Value': 'fake_value'}])
|
||||
self.addResourceCleanUp(self.client.delete_tags,
|
||||
Resources=[resource_id],
|
||||
Tags=[{'Key': tag_key}])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [resource_id]}])
|
||||
self.assertEqual(origin_count + 1, len(data['Tags']))
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-type', 'Values': [res_type]}])
|
||||
self.assertIn(tag_key, [k.get('Key') for k in data['Tags']])
|
||||
|
||||
describe_func(Filters=[{'Name': 'tag-key', 'Values': [tag_key]}])
|
||||
|
||||
self.client.delete_tags(Resources=[resource_id],
|
||||
Tags=[{'Key': tag_key}])
|
||||
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [resource_id]}])
|
||||
self.assertEqual(origin_count, len(data['Tags']))
|
||||
|
||||
def _test_tag_resource_negative(self, resource_id):
|
||||
data = self.client.describe_tags(
|
||||
Filters=[{'Name': 'resource-id', 'Values': [resource_id]}])
|
||||
self.assertEmpty(data['Tags'])
|
||||
|
||||
def _rollback(fn_data):
|
||||
self.client.delete_tags(Resources=[resource_id],
|
||||
Tags=[{'Key': tag_key}])
|
||||
|
||||
tag_key = data_utils.rand_name('tag-key')
|
||||
self.assertRaises('InvalidID',
|
||||
self.client.create_tags, rollback_fn=_rollback,
|
||||
Resources=[resource_id],
|
||||
Tags=[{'Key': tag_key, 'Value': 'fake_value'}])
|
||||
|
||||
@decorators.idempotent_id('36478dc6-cf3f-4a4b-b275-282ba147822b')
|
||||
def test_tag_image(self):
|
||||
image_id = CONF.aws.ebs_image_id
|
||||
if not image_id:
|
||||
image_id = CONF.aws.image_id
|
||||
if not image_id:
|
||||
raise self.skipException('aws or ebs image_id does not provided')
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_images(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['Images']))
|
||||
self.assertEqual(image_id, data['Images'][0]['ImageId'])
|
||||
|
||||
self._test_tag_resource(image_id, 'image', describe_func)
|
||||
|
||||
data = self.client.describe_images(ImageIds=[image_id])
|
||||
image = data['Images'][0]
|
||||
if 'KernelId' in image:
|
||||
image_id = image['KernelId']
|
||||
self._test_tag_resource(image_id, 'image', describe_func)
|
||||
if 'RamdiskId' in image:
|
||||
image_id = image['RamdiskId']
|
||||
self._test_tag_resource(image_id, 'image', describe_func)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('adc459f3-858d-4ce8-a097-549ab9350b18')
|
||||
def test_tag_dhcp_options(self):
|
||||
kwargs = {
|
||||
'DhcpConfigurations': [
|
||||
{'Key': 'domain-name',
|
||||
'Values': ['my.com']},
|
||||
],
|
||||
}
|
||||
data = self.client.create_dhcp_options(*[], **kwargs)
|
||||
options = data['DhcpOptions']
|
||||
res_id = options['DhcpOptionsId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_dhcp_options,
|
||||
DhcpOptionsId=res_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_dhcp_options(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['DhcpOptions']))
|
||||
self.assertEqual(res_id, data['DhcpOptions'][0]['DhcpOptionsId'])
|
||||
|
||||
self._test_tag_resource(res_id, 'dhcp-options', describe_func)
|
||||
|
||||
self.client.delete_dhcp_options(DhcpOptionsId=res_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('afa064b2-8caf-442d-b001-b6cb8120e57e')
|
||||
def test_tag_volume(self):
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_volumes(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
self.assertEqual(self.volume_id, data['Volumes'][0]['VolumeId'])
|
||||
|
||||
self._test_tag_resource(self.volume_id, 'volume', describe_func)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('96e581c6-8f38-41f9-9126-e35215c83d3e')
|
||||
def test_tag_address(self):
|
||||
kwargs = {
|
||||
'Domain': 'vpc',
|
||||
}
|
||||
data = self.client.allocate_address(*[], **kwargs)
|
||||
res_id = data['AllocationId']
|
||||
res_clean = self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=res_id)
|
||||
self.assertEqual('vpc', data['Domain'])
|
||||
|
||||
self._test_tag_resource_negative(res_id)
|
||||
|
||||
self.client.release_address(AllocationId=res_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@decorators.idempotent_id('f9a6dd26-b26f-4482-aad3-0b4f0e7cc3dd')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_tag_instance(self):
|
||||
instance_id = self.run_instance()
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_instances(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['Reservations']))
|
||||
self.assertEqual(1, len(data['Reservations'][0]['Instances']))
|
||||
self.assertEqual(instance_id,
|
||||
data['Reservations'][0]['Instances'][0]['InstanceId'])
|
||||
|
||||
self._test_tag_resource(instance_id, 'instance', describe_func)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('a223af28-b355-4404-a465-7fc9e9d71ad7')
|
||||
def test_tag_internet_gateway(self):
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_internet_gateway, InternetGatewayId=gw_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_internet_gateways(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['InternetGateways']))
|
||||
self.assertEqual(gw_id,
|
||||
data['InternetGateways'][0]['InternetGatewayId'])
|
||||
|
||||
self._test_tag_resource(gw_id, 'internet-gateway', describe_func)
|
||||
|
||||
self.client.delete_internet_gateway(InternetGatewayId=gw_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('4691eefb-c118-4595-a386-8a2abd5c0d77')
|
||||
def test_tag_network_interface(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(
|
||||
self.client.delete_vpc, VpcId=vpc_id)
|
||||
|
||||
cidr = '10.1.0.0/24'
|
||||
data = self.client.create_subnet(VpcId=vpc_id,
|
||||
CidrBlock=cidr)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
subnet_clean = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
|
||||
data = self.client.create_network_interface(SubnetId=subnet_id,
|
||||
Description=data_utils.rand_name('ni'))
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
res_clean = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_network_interfaces(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['NetworkInterfaces']))
|
||||
self.assertEqual(ni_id,
|
||||
data['NetworkInterfaces'][0]['NetworkInterfaceId'])
|
||||
|
||||
self._test_tag_resource(ni_id, 'network-interface', describe_func)
|
||||
|
||||
self.client.delete_network_interface(NetworkInterfaceId=ni_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_network_interface_waiter().wait_delete(ni_id)
|
||||
|
||||
self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(subnet_clean)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('384083a0-d492-4620-8093-166cd339ffaa')
|
||||
def test_tag_route_table(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(
|
||||
self.client.delete_vpc, VpcId=vpc_id)
|
||||
|
||||
data = self.client.create_route_table(VpcId=vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_route_tables(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
self.assertEqual(rt_id, data['RouteTables'][0]['RouteTableId'])
|
||||
|
||||
self._test_tag_resource(rt_id, 'route-table', describe_func)
|
||||
|
||||
self.client.delete_route_table(RouteTableId=rt_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('03b8cd38-3017-4a8f-b2e0-1c4ac5e7333d')
|
||||
def test_tag_security_group(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(
|
||||
self.client.delete_vpc, VpcId=vpc_id)
|
||||
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
data = self.client.create_security_group(VpcId=vpc_id,
|
||||
GroupName=name,
|
||||
Description=desc)
|
||||
group_id = data['GroupId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupId=group_id)
|
||||
time.sleep(2)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_security_groups(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['SecurityGroups']))
|
||||
self.assertEqual(group_id,
|
||||
data['SecurityGroups'][0]['GroupId'])
|
||||
|
||||
self._test_tag_resource(group_id, 'security-group', describe_func)
|
||||
|
||||
self.client.delete_security_group(GroupId=group_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@decorators.idempotent_id('bed98f9c-f987-4192-afd8-4bdf35ac916e')
|
||||
def test_tag_snapshot(self):
|
||||
data = self.client.create_snapshot(VolumeId=self.volume_id)
|
||||
snapshot_id = data['SnapshotId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_snapshots(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['Snapshots']))
|
||||
self.assertEqual(snapshot_id, data['Snapshots'][0]['SnapshotId'])
|
||||
|
||||
self._test_tag_resource(snapshot_id, 'snapshot', describe_func)
|
||||
|
||||
self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_snapshot_waiter().wait_delete(snapshot_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('3a6f64fc-d2d4-496d-bf30-3ee0efe04e42')
|
||||
def test_tag_subnet(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(
|
||||
self.client.delete_vpc, VpcId=vpc_id)
|
||||
|
||||
cidr = '10.1.0.0/24'
|
||||
data = self.client.create_subnet(VpcId=vpc_id,
|
||||
CidrBlock=cidr)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_subnets(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['Subnets']))
|
||||
self.assertEqual(subnet_id, data['Subnets'][0]['SubnetId'])
|
||||
|
||||
self._test_tag_resource(subnet_id, 'subnet', describe_func)
|
||||
|
||||
self.client.delete_subnet(SubnetId=subnet_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_subnet_waiter().wait_delete(subnet_id)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('0667c68b-9d3c-4599-9335-0cee68ba5d80')
|
||||
def test_tag_vpc(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(
|
||||
self.client.delete_vpc, VpcId=vpc_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_vpcs(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['Vpcs']))
|
||||
self.assertEqual(vpc_id, data['Vpcs'][0]['VpcId'])
|
||||
|
||||
self._test_tag_resource(vpc_id, 'vpc', describe_func)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('07b2f20d-6b26-4c3d-9d32-93f98f187d78')
|
||||
def test_tag_customer_gateway(self):
|
||||
data = self.client.create_customer_gateway(
|
||||
Type='ipsec.1', PublicIp='198.51.100.77', BgpAsn=65000)
|
||||
cgw_id = data['CustomerGateway']['CustomerGatewayId']
|
||||
self.addResourceCleanUp(self.client.delete_customer_gateway,
|
||||
CustomerGatewayId=cgw_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_customer_gateways(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['CustomerGateways']))
|
||||
self.assertEqual(cgw_id,
|
||||
data['CustomerGateways'][0]['CustomerGatewayId'])
|
||||
|
||||
self._test_tag_resource(cgw_id, 'customer-gateway', describe_func)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@base.skip_without_network_feature('vpnaas')
|
||||
@decorators.idempotent_id('a0437171-81a1-4871-9b71-c7629b25c337')
|
||||
def test_tag_vpn_gateway(self):
|
||||
data = self.client.create_vpn_gateway(Type='ipsec.1')
|
||||
vgw_id = data['VpnGateway']['VpnGatewayId']
|
||||
self.addResourceCleanUp(self.client.delete_vpn_gateway,
|
||||
VpnGatewayId=vgw_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_vpn_gateways(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['VpnGateways']))
|
||||
self.assertEqual(vgw_id,
|
||||
data['VpnGateways'][0]['VpnGatewayId'])
|
||||
|
||||
self._test_tag_resource(vgw_id, 'vpn-gateway', describe_func)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@base.skip_without_network_feature('vpnaas')
|
||||
@decorators.idempotent_id('ecd343b4-f448-4990-880d-02a68febc9cf')
|
||||
def test_tag_vpn_connection(self):
|
||||
data = self.client.create_customer_gateway(
|
||||
Type='ipsec.1', PublicIp='198.51.100.77', BgpAsn=65000)
|
||||
cgw_id = data['CustomerGateway']['CustomerGatewayId']
|
||||
self.addResourceCleanUp(self.client.delete_customer_gateway,
|
||||
CustomerGatewayId=cgw_id)
|
||||
|
||||
data = self.client.create_vpn_gateway(Type='ipsec.1')
|
||||
vgw_id = data['VpnGateway']['VpnGatewayId']
|
||||
self.addResourceCleanUp(self.client.delete_vpn_gateway,
|
||||
VpnGatewayId=vgw_id)
|
||||
|
||||
data = self.client.create_vpn_connection(
|
||||
CustomerGatewayId=cgw_id, VpnGatewayId=vgw_id,
|
||||
Options={'StaticRoutesOnly': True}, Type='ipsec.1')
|
||||
vpn_id = data['VpnConnection']['VpnConnectionId']
|
||||
vpn_clean = self.addResourceCleanUp(self.client.delete_vpn_connection,
|
||||
VpnConnectionId=vpn_id)
|
||||
|
||||
def describe_func(*args, **kwargs):
|
||||
data = self.client.describe_vpn_connections(*args, **kwargs)
|
||||
self.assertEqual(1, len(data['VpnConnections']))
|
||||
self.assertEqual(vpn_id,
|
||||
data['VpnConnections'][0]['VpnConnectionId'])
|
||||
|
||||
self._test_tag_resource(vpn_id, 'vpn-connection', describe_func)
|
||||
|
||||
self.client.delete_vpn_connection(VpnConnectionId=vpn_id)
|
||||
vpn_waiter = self.get_vpn_connection_waiter()
|
||||
self.cancelResourceCleanUp(vpn_clean)
|
||||
vpn_waiter.wait_delete(vpn_id)
|
|
@ -1,411 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class VolumeTest(base.EC2TestCase):
|
||||
|
||||
@decorators.idempotent_id('51fd4d06-7b00-427a-9d69-6ecd076c219a')
|
||||
def test_create_delete_volume(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
self.assertEqual('standard', data['VolumeType'])
|
||||
self.assertEqual(1, data['Size'])
|
||||
if 'Encrypted' in data:
|
||||
self.assertFalse(data['Encrypted'])
|
||||
self.assertIsNotNone(data['CreateTime'])
|
||||
self.assertEqual(CONF.aws.aws_zone, data['AvailabilityZone'])
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
self.assertRaises('InvalidVolume.NotFound',
|
||||
self.client.describe_volumes,
|
||||
VolumeIds=[volume_id])
|
||||
|
||||
self.assertRaises('InvalidVolume.NotFound',
|
||||
self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
@decorators.idempotent_id('a7f1c4f8-2153-4d09-b5d5-bf087ea2f6ed')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Encryption is not implemented")
|
||||
def test_create_encrypted_volume(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone,
|
||||
'Encrypted': True,
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
self.assertTrue(data['Encrypted'])
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
@decorators.idempotent_id('16c97f73-c4f2-4e91-9506-4f6da4a33f8a')
|
||||
def test_describe_volumes(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id_ext = data['VolumeId']
|
||||
res_clean_ext = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id_ext)
|
||||
self.get_volume_waiter().wait_available(volume_id_ext)
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
|
||||
volume = data['Volumes'][0]
|
||||
self.assertEqual(volume_id, volume['VolumeId'])
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
self.assertEqual('standard', volume['VolumeType'])
|
||||
self.assertEqual(1, volume['Size'])
|
||||
if 'Encrypted' in volume:
|
||||
self.assertFalse(volume['Encrypted'])
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id_ext)
|
||||
self.cancelResourceCleanUp(res_clean_ext)
|
||||
self.get_volume_waiter().wait_delete(volume_id_ext)
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
@decorators.idempotent_id('30697dd5-12e7-4dd3-8cf8-5bdb296f26d8')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Volume statuses are not implemented")
|
||||
def test_describe_volume_status(self):
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
res_clean = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
data = self.client.describe_volume_status(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['VolumeStatuses']))
|
||||
|
||||
volume_status = data['VolumeStatuses'][0]
|
||||
self.assertIn('Actions', volume_status)
|
||||
self.assertIn('Events', volume_status)
|
||||
self.assertIn('VolumeStatus', volume_status)
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
@decorators.idempotent_id('b0116edc-250c-4083-b1ad-66c0eb984415')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "ebs image id is not defined")
|
||||
def test_attach_detach_volume(self):
|
||||
clean_dict = {}
|
||||
instance_id = self.run_instance(ImageId=CONF.aws.ebs_image_id,
|
||||
clean_dict=clean_dict)
|
||||
clean_i = clean_dict['instance']
|
||||
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_v = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
kwargs = {
|
||||
'Device': '/dev/sdh',
|
||||
'InstanceId': instance_id,
|
||||
'VolumeId': volume_id,
|
||||
}
|
||||
self.client.attach_volume(*[], **kwargs)
|
||||
clean_vi = self.addResourceCleanUp(self.client.detach_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id, final_set=('attached'))
|
||||
|
||||
# reorder cleanups to avoid error on volume delete
|
||||
self.cancelResourceCleanUp(clean_i)
|
||||
clean_i = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
volume = data['Volumes'][0]
|
||||
self.assertEqual('in-use', volume['State'])
|
||||
self.assertEqual(1, len(volume['Attachments']))
|
||||
attachment = volume['Attachments'][0]
|
||||
self.assertFalse(attachment['DeleteOnTermination'])
|
||||
self.assertIsNotNone(attachment['Device'])
|
||||
self.assertEqual(instance_id, attachment['InstanceId'])
|
||||
self.assertEqual(volume_id, attachment['VolumeId'])
|
||||
|
||||
data = self.client.describe_instances(InstanceIds=[instance_id])
|
||||
self.assertEqual(1, len(data.get('Reservations', [])))
|
||||
self.assertEqual(1, len(data['Reservations'][0].get('Instances', [])))
|
||||
bdms = data['Reservations'][0]['Instances'][0]['BlockDeviceMappings']
|
||||
self.assertNotEmpty(bdms)
|
||||
self.assertIn('DeviceName', bdms[0])
|
||||
self.assertIn('Ebs', bdms[0])
|
||||
|
||||
# stop instance to prevent 'busy' state of detached volume
|
||||
data = self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
self.client.detach_volume(VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_delete(volume_id)
|
||||
self.cancelResourceCleanUp(clean_vi)
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
volume = data['Volumes'][0]
|
||||
self.assertEqual('available', volume['State'])
|
||||
self.assertEqual(0, len(volume['Attachments']))
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_v)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(clean_i)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('c4b470b7-0825-418f-bc76-533f84247878')
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_attaching_stage(self):
|
||||
data = self.client.create_volume(
|
||||
AvailabilityZone=CONF.aws.aws_zone, Size=1)
|
||||
volume_id = data['VolumeId']
|
||||
clean_v = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
clean_dict = {}
|
||||
instance_id = self.run_instance(ImageId=CONF.aws.ebs_image_id,
|
||||
clean_dict=clean_dict)
|
||||
clean_i = clean_dict['instance']
|
||||
|
||||
device_name = '/dev/xvdh'
|
||||
kwargs = {
|
||||
'Device': device_name,
|
||||
'InstanceId': instance_id,
|
||||
'VolumeId': volume_id,
|
||||
}
|
||||
data = self.client.attach_volume(*[], **kwargs)
|
||||
self.assertEqual('attaching', data['State'])
|
||||
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
bdt = self.get_instance_bdm(instance_id, device_name)
|
||||
self.assertIsNotNone(bdt)
|
||||
self.assertEqual('attaching', bdt['Ebs']['Status'])
|
||||
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id, final_set=('attached'))
|
||||
|
||||
# stop instance to prevent 'busy' state of detached volume
|
||||
data = self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
self.client.detach_volume(VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_delete(volume_id)
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_v)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(clean_i)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('949ced35-fb66-4e87-afd8-f64de3dd20e9')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Volume statuses are not implemented")
|
||||
@testtools.skipUnless(CONF.aws.ebs_image_id, "EBS image id is not defined")
|
||||
def test_delete_detach_attached_volume(self):
|
||||
instance_id = self.run_instance(ImageId=CONF.aws.ebs_image_id)
|
||||
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_v = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
kwargs = {
|
||||
'Device': '/dev/sdh',
|
||||
'InstanceId': instance_id,
|
||||
'VolumeId': volume_id,
|
||||
}
|
||||
self.client.attach_volume(*[], **kwargs)
|
||||
clean_vi = self.addResourceCleanUp(self.client.detach_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id, final_set=('attached'))
|
||||
|
||||
self.assertRaises('VolumeInUse',
|
||||
self.client.attach_volume,
|
||||
**kwargs)
|
||||
|
||||
kwargs['Device'] = '/dev/sdi'
|
||||
self.assertRaises('VolumeInUse',
|
||||
self.client.attach_volume,
|
||||
**kwargs)
|
||||
|
||||
self.assertRaises('VolumeInUse',
|
||||
self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
# stop instance to prevent 'busy' state of detached volume
|
||||
data = self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
self.client.detach_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_vi)
|
||||
self.get_volume_attachment_waiter().wait_delete(volume_id)
|
||||
|
||||
self.assertRaises('IncorrectState',
|
||||
self.client.detach_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_v)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
self.assertRaises('InvalidVolume.NotFound',
|
||||
self.client.detach_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('c37b01f7-5b27-4773-9278-9e0b8eaccb5f')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_volume_auto_termination_swithed_off(self):
|
||||
instance_id = self.run_instance()
|
||||
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
clean_v = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
kwargs = {
|
||||
'Device': '/dev/sdh',
|
||||
'InstanceId': instance_id,
|
||||
'VolumeId': volume_id,
|
||||
}
|
||||
self.client.attach_volume(*[], **kwargs)
|
||||
self.addResourceCleanUp(self.client.detach_volume, VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id, final_set=('attached'))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
volume = data['Volumes'][0]
|
||||
self.assertEqual('available', volume['State'])
|
||||
if 'Attachments' in volume:
|
||||
self.assertEqual(0, len(volume['Attachments']))
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_v)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
@decorators.idempotent_id('c8649cab-e1f4-42f7-9578-8e72d06534ba')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"modify_instance_attribute is not implemented")
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_volume_auto_termination_swithed_on(self):
|
||||
instance_id = self.run_instance()
|
||||
|
||||
kwargs = {
|
||||
'Size': 1,
|
||||
'AvailabilityZone': CONF.aws.aws_zone
|
||||
}
|
||||
data = self.client.create_volume(*[], **kwargs)
|
||||
volume_id = data['VolumeId']
|
||||
self.addResourceCleanUp(self.client.delete_volume, VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
kwargs = {
|
||||
'Device': '/dev/sdh',
|
||||
'InstanceId': instance_id,
|
||||
'VolumeId': volume_id,
|
||||
}
|
||||
self.client.attach_volume(*[], **kwargs)
|
||||
self.addResourceCleanUp(self.client.detach_volume, VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id, final_set=('attached'))
|
||||
|
||||
kwargs = {
|
||||
'InstanceId': instance_id,
|
||||
'BlockDeviceMappings': [{'DeviceName': '/dev/sdh',
|
||||
'Ebs': {'VolumeId': volume_id,
|
||||
'DeleteOnTermination': True}}],
|
||||
}
|
||||
self.client.modify_instance_attribute(*[], **kwargs)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
# volume should be deleted by the Cloud
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
|
@ -1,208 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class VPCTest(base.EC2TestCase):
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VPCTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
|
||||
@decorators.idempotent_id('446b19ba-2b70-4f52-9e32-82e04771cb70')
|
||||
def test_create_delete_vpc(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
|
||||
self.assertEqual(cidr, data['Vpc']['CidrBlock'])
|
||||
if CONF.aws.run_incompatible_tests:
|
||||
# NOTE(andrey-mp): not ready
|
||||
self.assertEqual('default', data['Vpc']['InstanceTenancy'])
|
||||
self.assertIsNotNone(data['Vpc'].get('DhcpOptionsId'))
|
||||
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
self.assertRaises('InvalidVpcID.NotFound',
|
||||
self.client.describe_vpcs,
|
||||
VpcIds=[vpc_id])
|
||||
|
||||
self.assertRaises('InvalidVpcID.NotFound',
|
||||
self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
|
||||
@decorators.idempotent_id('de300ce9-41a4-4b88-a991-99186e8c97b4')
|
||||
def test_create_more_than_one_vpc(self):
|
||||
cidr = '10.0.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id1 = data['Vpc']['VpcId']
|
||||
rc1 = self.addResourceCleanUp(self.client.delete_vpc, VpcId=vpc_id1)
|
||||
self.get_vpc_waiter().wait_available(vpc_id1)
|
||||
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id2 = data['Vpc']['VpcId']
|
||||
rc2 = self.addResourceCleanUp(self.client.delete_vpc, VpcId=vpc_id2)
|
||||
self.get_vpc_waiter().wait_available(vpc_id2)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id1)
|
||||
self.cancelResourceCleanUp(rc1)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id1)
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id2)
|
||||
self.cancelResourceCleanUp(rc2)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id2)
|
||||
|
||||
@decorators.idempotent_id('011bd6e0-65c3-4716-a1f3-ba6cdb477b19')
|
||||
def test_describe_vpcs_base(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
# NOTE(andrey-mp): by real id
|
||||
data = self.client.describe_vpcs(VpcIds=[vpc_id])
|
||||
self.assertEqual(1, len(data['Vpcs']))
|
||||
|
||||
# NOTE(andrey-mp): by fake id
|
||||
self.assertRaises('InvalidVpcID.NotFound',
|
||||
self.client.describe_vpcs,
|
||||
VpcIds=['vpc-0'])
|
||||
|
||||
self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@decorators.idempotent_id('9c8735b9-f745-49a0-b68d-33f771bac660')
|
||||
def test_describe_vpcs_filters(self):
|
||||
cidr = '10.163.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
# NOTE(andrey-mp): by filter real cidr
|
||||
data = self.client.describe_vpcs(
|
||||
Filters=[{'Name': 'cidr', 'Values': [cidr]}])
|
||||
self.assertEqual(1, len(data['Vpcs']))
|
||||
|
||||
# NOTE(andrey-mp): by filter fake cidr
|
||||
data = self.client.describe_vpcs(
|
||||
Filters=[{'Name': 'cidr', 'Values': ['123.0.0.0/16']}])
|
||||
self.assertEqual(0, len(data['Vpcs']))
|
||||
|
||||
# NOTE(andrey-mp): by fake filter
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_vpcs,
|
||||
Filters=[{'Name': 'fake', 'Values': ['fake']}])
|
||||
|
||||
data = self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
@decorators.idempotent_id('3070ea61-992b-4711-a874-322c6c672204')
|
||||
@testtools.skipUnless(CONF.aws.run_incompatible_tests,
|
||||
"Invalid request on checking vpc atributes.")
|
||||
def test_vpc_attributes(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
self._check_attribute(vpc_id, 'EnableDnsHostnames')
|
||||
self._check_attribute(vpc_id, 'EnableDnsSupport')
|
||||
|
||||
data = self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
||||
|
||||
def _check_attribute(self, vpc_id, attribute):
|
||||
req_attr = attribute[0].lower() + attribute[1:]
|
||||
data = self.client.describe_vpc_attribute(VpcId=vpc_id,
|
||||
Attribute=req_attr)
|
||||
attr = data[attribute].get('Value')
|
||||
self.assertIsNotNone(attr)
|
||||
|
||||
kwargs = {'VpcId': vpc_id, attribute: {'Value': not attr}}
|
||||
data = self.client.modify_vpc_attribute(*[], **kwargs)
|
||||
data = self.client.describe_vpc_attribute(VpcId=vpc_id,
|
||||
Attribute=req_attr)
|
||||
self.assertNotEqual(attr, data[attribute].get('Value'))
|
||||
|
||||
@decorators.idempotent_id('8c5f1e82-05da-40e0-8ee8-640db2d94dd6')
|
||||
def test_create_with_invalid_cidr(self):
|
||||
def _rollback(fn_data):
|
||||
self.client.delete_vpc(VpcId=fn_data['Vpc']['VpcId'])
|
||||
|
||||
# NOTE(andrey-mp): The largest uses a /16 netmask
|
||||
self.assertRaises('InvalidVpc.Range',
|
||||
self.client.create_vpc, rollback_fn=_rollback,
|
||||
CidrBlock='10.0.0.0/15')
|
||||
|
||||
# NOTE(andrey-mp): The smallest VPC you can create uses a /28 netmask
|
||||
self.assertRaises('InvalidVpc.Range',
|
||||
self.client.create_vpc, rollback_fn=_rollback,
|
||||
CidrBlock='10.0.0.0/29')
|
||||
|
||||
@decorators.idempotent_id('5abb2ff0-8ea2-4e02-b9a4-95a371982b82')
|
||||
def test_describe_non_existing_vpc_by_id(self):
|
||||
vpc_id = 'vpc-00000000'
|
||||
self.assertRaises('InvalidVpcID.NotFound',
|
||||
self.client.describe_vpcs,
|
||||
VpcIds=[vpc_id])
|
||||
|
||||
@decorators.idempotent_id('e99d81f1-902a-46b0-afc8-c64e6d548891')
|
||||
def test_describe_non_existing_vpc_by_cidr(self):
|
||||
data = self.client.describe_vpcs(
|
||||
Filters=[{'Name': 'cidr', 'Values': ['123.0.0.0/16']}])
|
||||
self.assertEqual(0, len(data['Vpcs']))
|
||||
|
||||
@decorators.idempotent_id('62263b68-6991-4bbe-b7b2-9997a84fd0a5')
|
||||
def test_describe_with_invalid_filter(self):
|
||||
cidr = '10.1.0.0/16'
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
dv_clean = self.addResourceCleanUp(self.client.delete_vpc,
|
||||
VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_vpcs,
|
||||
Filters=[{'Name': 'unknown', 'Values': ['unknown']}])
|
||||
|
||||
data = self.client.delete_vpc(VpcId=vpc_id)
|
||||
self.cancelResourceCleanUp(dv_clean)
|
||||
self.get_vpc_waiter().wait_delete(vpc_id)
|
|
@ -1,113 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import botocore.exceptions
|
||||
from lxml import etree
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class VpnConnectionTest(base.EC2TestCase):
|
||||
|
||||
CUSTOMER_GATEWAY_IP = '198.51.100.77'
|
||||
CUSTOMER_VPN_CIDR = '172.16.25.0/24'
|
||||
cgw_id = None
|
||||
vgw_id = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VpnConnectionTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
base.check_network_feature_enabled('vpnaas')
|
||||
|
||||
data = cls.client.create_customer_gateway(
|
||||
Type='ipsec.1', PublicIp=cls.CUSTOMER_GATEWAY_IP, BgpAsn=65000)
|
||||
cls.cgw_id = data['CustomerGateway']['CustomerGatewayId']
|
||||
cls.addResourceCleanUpStatic(
|
||||
cls.client.delete_customer_gateway, CustomerGatewayId=cls.cgw_id)
|
||||
cls.get_customer_gateway_waiter().wait_available(cls.cgw_id)
|
||||
|
||||
data = cls.client.create_vpn_gateway(
|
||||
Type='ipsec.1', AvailabilityZone=CONF.aws.aws_zone)
|
||||
cls.vgw_id = data['VpnGateway']['VpnGatewayId']
|
||||
cls.addResourceCleanUpStatic(
|
||||
cls.client.delete_vpn_gateway, VpnGatewayId=cls.vgw_id)
|
||||
cls.get_vpn_gateway_waiter().wait_available(cls.vgw_id)
|
||||
|
||||
@decorators.idempotent_id('57426aab-cf2d-4114-a11d-2bd6642ac606')
|
||||
def test_create_delete_vpn_connection(self):
|
||||
data = self.client.create_vpn_connection(
|
||||
CustomerGatewayId=self.cgw_id, VpnGatewayId=self.vgw_id,
|
||||
Options={'StaticRoutesOnly': True}, Type='ipsec.1')
|
||||
vpn_id = data['VpnConnection']['VpnConnectionId']
|
||||
vpn_clean = self.addResourceCleanUp(
|
||||
self.client.delete_vpn_connection, VpnConnectionId=vpn_id)
|
||||
vpn_config = etree.fromstring(
|
||||
data['VpnConnection']['CustomerGatewayConfiguration'])
|
||||
psks = vpn_config.xpath(
|
||||
'/vpn_connection/ipsec_tunnel/ike/pre_shared_key')
|
||||
self.assertNotEmpty(psks)
|
||||
self.assertTrue(psks[0].text)
|
||||
vpn_waiter = self.get_vpn_connection_waiter()
|
||||
vpn_waiter.wait_available(vpn_id)
|
||||
|
||||
self.client.delete_vpn_connection(VpnConnectionId=vpn_id)
|
||||
self.cancelResourceCleanUp(vpn_clean)
|
||||
vpn_waiter.wait_delete(vpn_id)
|
||||
|
||||
try:
|
||||
data = self.client.describe_vpn_connections(
|
||||
VpnConnectionIds=[vpn_id])
|
||||
self.assertEqual(1, len(data['VpnConnections']))
|
||||
self.assertEqual('deleted', data['VpnConnections'][0]['State'])
|
||||
except botocore.exceptions.ClientError as ex:
|
||||
self.assertEqual('InvalidVpnConnectionID.NotFound',
|
||||
ex.response['Error']['Code'])
|
||||
|
||||
@decorators.idempotent_id('6fa8c58d-876b-4d3f-85ba-e972a9d6db3b')
|
||||
def test_create_delete_vpn_connection_route(self):
|
||||
data = self.client.create_vpn_connection(
|
||||
CustomerGatewayId=self.cgw_id, VpnGatewayId=self.vgw_id,
|
||||
Options={'StaticRoutesOnly': True}, Type='ipsec.1')
|
||||
vpn_id = data['VpnConnection']['VpnConnectionId']
|
||||
self.addResourceCleanUp(
|
||||
self.client.delete_vpn_connection, VpnConnectionId=vpn_id)
|
||||
vpn_waiter = self.get_vpn_connection_waiter()
|
||||
vpn_waiter.wait_available(vpn_id)
|
||||
|
||||
data = self.client.create_vpn_connection_route(
|
||||
VpnConnectionId=vpn_id,
|
||||
DestinationCidrBlock=self.CUSTOMER_VPN_CIDR)
|
||||
|
||||
data = self.client.describe_vpn_connections(VpnConnectionIds=[vpn_id])
|
||||
self.assertEqual(1, len(data['VpnConnections'][0]['Routes']))
|
||||
self.assertEqual(
|
||||
self.CUSTOMER_VPN_CIDR,
|
||||
data['VpnConnections'][0]['Routes'][0]['DestinationCidrBlock'])
|
||||
route_waiter = self.get_vpn_connection_route_waiter(
|
||||
self.CUSTOMER_VPN_CIDR)
|
||||
route_waiter.wait_available(vpn_id)
|
||||
|
||||
data = self.client.delete_vpn_connection_route(
|
||||
VpnConnectionId=vpn_id,
|
||||
DestinationCidrBlock=self.CUSTOMER_VPN_CIDR)
|
||||
data = self.client.describe_vpn_connections(VpnConnectionIds=[vpn_id])
|
||||
route_waiter.wait_delete(vpn_id)
|
|
@ -1,93 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import botocore.exceptions
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
class VpnGatewayTest(base.EC2TestCase):
|
||||
|
||||
VPC_CIDR = '10.41.0.0/20'
|
||||
vpc_id = None
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VpnGatewayTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
base.check_network_feature_enabled('vpnaas')
|
||||
|
||||
data = cls.client.create_vpc(CidrBlock=cls.VPC_CIDR)
|
||||
cls.vpc_id = data['Vpc']['VpcId']
|
||||
cls.get_vpc_waiter().wait_available(cls.vpc_id)
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_vpc, VpcId=cls.vpc_id)
|
||||
|
||||
@decorators.idempotent_id('d38c0185-782c-4da3-b02c-9cd7bf91b001')
|
||||
def test_create_delete_vpn_gateway(self):
|
||||
data = self.client.create_vpn_gateway(
|
||||
Type='ipsec.1', AvailabilityZone=CONF.aws.aws_zone)
|
||||
vgw_id = data['VpnGateway']['VpnGatewayId']
|
||||
vgw_clean = self.addResourceCleanUp(
|
||||
self.client.delete_vpn_gateway, VpnGatewayId=vgw_id)
|
||||
self.get_vpn_gateway_waiter().wait_available(vgw_id)
|
||||
|
||||
self.client.delete_vpn_gateway(VpnGatewayId=vgw_id)
|
||||
self.cancelResourceCleanUp(vgw_clean)
|
||||
self.get_vpn_gateway_waiter().wait_delete(vgw_id)
|
||||
|
||||
try:
|
||||
data = self.client.describe_vpn_gateways(
|
||||
VpnGatewayIds=[vgw_id])
|
||||
self.assertEqual(1, len(data['VpnGateways']))
|
||||
self.assertEqual('deleted', data['VpnGateways'][0]['State'])
|
||||
except botocore.exceptions.ClientError as ex:
|
||||
self.assertEqual('InvalidVpnGatewayID.NotFound',
|
||||
ex.response['Error']['Code'])
|
||||
|
||||
@decorators.idempotent_id('1d76b335-57ba-449a-9751-af75a8a7d11c')
|
||||
def test_attach_detach_vpn_gateway(self):
|
||||
data = self.client.create_vpn_gateway(
|
||||
Type='ipsec.1', AvailabilityZone=CONF.aws.aws_zone)
|
||||
vgw_id = data['VpnGateway']['VpnGatewayId']
|
||||
self.addResourceCleanUp(self.client.delete_vpn_gateway,
|
||||
VpnGatewayId=vgw_id)
|
||||
self.get_vpn_gateway_waiter().wait_available(vgw_id)
|
||||
|
||||
data = self.client.attach_vpn_gateway(VpnGatewayId=vgw_id,
|
||||
VpcId=self.vpc_id)
|
||||
attach_clean = self.addResourceCleanUp(
|
||||
self.client.detach_vpn_gateway,
|
||||
VpnGatewayId=vgw_id, VpcId=self.vpc_id)
|
||||
self.assertIn('VpcAttachment', data)
|
||||
self.assertEqual(self.vpc_id, data['VpcAttachment']['VpcId'])
|
||||
attach_waiter = self.get_vpn_gateway_attachment_waiter()
|
||||
attach_waiter.wait_available(vgw_id, 'attached')
|
||||
|
||||
data = self.client.detach_vpn_gateway(VpnGatewayId=vgw_id,
|
||||
VpcId=self.vpc_id)
|
||||
self.cancelResourceCleanUp(attach_clean)
|
||||
attach_waiter.wait_delete(vgw_id)
|
||||
|
||||
data = self.client.describe_vpn_gateways(VpnGatewayIds=[vgw_id])
|
||||
self.assertEqual(
|
||||
'detached',
|
||||
(data['VpnGateways'][0]['VpcAttachments'] or
|
||||
[{'State': 'detached'}])[0]['State'])
|
|
@ -1,888 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import functools
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
|
||||
import botocore.exceptions
|
||||
from oslo_log import log
|
||||
import six
|
||||
from tempest.lib import base
|
||||
from tempest.lib import exceptions
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import botocoreclient
|
||||
from ec2api.tests.functional import config as cfg
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
logging.getLogger('botocore').setLevel(logging.INFO)
|
||||
logging.getLogger(
|
||||
'botocore.vendored.requests.packages.urllib3.connectionpool'
|
||||
).setLevel(logging.WARNING)
|
||||
logging.getLogger('paramiko.transport').setLevel(logging.WARNING)
|
||||
|
||||
|
||||
class EC2Waiter(object):
|
||||
|
||||
def __init__(self, wait_func):
|
||||
self.wait_func = wait_func
|
||||
self.default_timeout = CONF.aws.build_timeout
|
||||
self.default_check_interval = CONF.aws.build_interval
|
||||
|
||||
def _state_wait(self, f, f_args=None, f_kwargs=None,
|
||||
final_set=set(), error_set=('error')):
|
||||
if not isinstance(final_set, set):
|
||||
final_set = set((final_set,))
|
||||
if not isinstance(error_set, set):
|
||||
error_set = set((error_set,))
|
||||
interval = self.default_check_interval
|
||||
start_time = time.time()
|
||||
args = f_args if f_args is not None else []
|
||||
kwargs = f_kwargs if f_kwargs is not None else {}
|
||||
try:
|
||||
old_status = status = f(*args, **kwargs)
|
||||
except exceptions.NotFound:
|
||||
old_status = status = "NotFound"
|
||||
while True:
|
||||
if status != old_status:
|
||||
LOG.info('State transition "%s" ==> "%s" %d second',
|
||||
old_status, status, time.time() - start_time)
|
||||
if status in final_set:
|
||||
return status
|
||||
if error_set is not None and status in error_set:
|
||||
raise testtools.TestCase.failureException(
|
||||
'State changes to error state! '
|
||||
'While waiting for %s at "%s"' %
|
||||
(final_set, status))
|
||||
dtime = time.time() - start_time
|
||||
if dtime > self.default_timeout:
|
||||
raise testtools.TestCase.failureException(
|
||||
'State change timeout exceeded! '
|
||||
'(%ds) While waiting for %s at "%s"' %
|
||||
(dtime, final_set, status))
|
||||
time.sleep(interval)
|
||||
interval += self.default_check_interval
|
||||
old_status = status
|
||||
try:
|
||||
status = f(*args, **kwargs)
|
||||
except exceptions.NotFound:
|
||||
status = "NotFound"
|
||||
|
||||
def _state_wait_gone(self, f, f_args=None, f_kwargs=None):
|
||||
interval = self.default_check_interval
|
||||
start_time = time.time()
|
||||
args = f_args if f_args is not None else []
|
||||
kwargs = f_kwargs if f_kwargs is not None else {}
|
||||
try:
|
||||
old_status = status = f(*args, **kwargs)
|
||||
while True:
|
||||
if status != old_status:
|
||||
LOG.info('State transition "%s" ==> "%s" %d second',
|
||||
old_status, status, time.time() - start_time)
|
||||
dtime = time.time() - start_time
|
||||
if dtime > self.default_timeout:
|
||||
raise testtools.TestCase.failureException(
|
||||
"State change timeout exceeded while waiting"
|
||||
" for deleting")
|
||||
time.sleep(interval)
|
||||
interval += self.default_check_interval
|
||||
old_status = status
|
||||
status = f(*args, **kwargs)
|
||||
except exceptions.NotFound:
|
||||
pass
|
||||
|
||||
def wait_available(self, obj_id, final_set=('available')):
|
||||
self._state_wait(self.wait_func, f_args=[obj_id],
|
||||
final_set=final_set)
|
||||
|
||||
def wait_delete(self, obj_id):
|
||||
self._state_wait_gone(self.wait_func, f_args=[obj_id])
|
||||
|
||||
def wait_no_exception(self, *args, **kwargs):
|
||||
interval = self.default_check_interval
|
||||
start_time = time.time()
|
||||
while True:
|
||||
try:
|
||||
self.wait_func(*args, **kwargs)
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
dtime = time.time() - start_time
|
||||
if dtime > self.default_timeout:
|
||||
raise testtools.TestCase.failureException(
|
||||
"Timeout exceeded while waiting")
|
||||
time.sleep(interval)
|
||||
interval += self.default_check_interval
|
||||
|
||||
def wait_for_result(self, *args, **kwargs):
|
||||
interval = self.default_check_interval
|
||||
start_time = time.time()
|
||||
while True:
|
||||
result = self.wait_func(*args, **kwargs)
|
||||
if result:
|
||||
return result
|
||||
|
||||
dtime = time.time() - start_time
|
||||
if dtime > self.default_timeout:
|
||||
raise testtools.TestCase.failureException(
|
||||
"Timeout exceeded while waiting")
|
||||
time.sleep(interval)
|
||||
interval += self.default_check_interval
|
||||
|
||||
|
||||
def safe_setup(f):
|
||||
"""A decorator used to wrap the setUpClass for safe setup."""
|
||||
|
||||
def decorator(cls):
|
||||
try:
|
||||
f(cls)
|
||||
except Exception as se:
|
||||
exc_info = sys.exc_info()
|
||||
LOG.exception("setUpClass failed: %s" % se)
|
||||
try:
|
||||
cls.tearDownClass()
|
||||
except Exception as te:
|
||||
LOG.exception("tearDownClass failed: %s" % te)
|
||||
six.reraise(*exc_info)
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def get_device_name_prefix(device_name):
|
||||
"""Return device name without device number.
|
||||
|
||||
/dev/sda1 -> /dev/sd
|
||||
/dev/vda -> /dev/vd
|
||||
"""
|
||||
dev_num_pos = 0
|
||||
while '0' <= device_name[dev_num_pos - 1] <= '9':
|
||||
dev_num_pos -= 1
|
||||
return device_name[:dev_num_pos - 1]
|
||||
|
||||
|
||||
class TesterStateHolder(object):
|
||||
|
||||
ec2_client = None
|
||||
_instance = None
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
if not cls._instance:
|
||||
cls._instance = super(TesterStateHolder, cls).__new__(
|
||||
cls, *args, **kwargs)
|
||||
return cls._instance
|
||||
|
||||
_ec2_enabled = None
|
||||
_vpc_enabled = None
|
||||
|
||||
def get_ec2_enabled(self):
|
||||
if self._ec2_enabled is None:
|
||||
self._fill_attributes()
|
||||
return self._ec2_enabled
|
||||
|
||||
def get_vpc_enabled(self):
|
||||
if self._vpc_enabled is None:
|
||||
self._fill_attributes()
|
||||
return self._vpc_enabled
|
||||
|
||||
def _fill_attributes(self):
|
||||
self._ec2_enabled = False
|
||||
self._vpc_enabled = False
|
||||
data = self.ec2_client.describe_account_attributes()
|
||||
for item in data.get('AccountAttributes', []):
|
||||
if item['AttributeName'] == 'supported-platforms':
|
||||
for value in item['AttributeValues']:
|
||||
if value['AttributeValue'] == 'VPC':
|
||||
self._vpc_enabled = True
|
||||
if value['AttributeValue'] == 'EC2':
|
||||
self._ec2_enabled = True
|
||||
|
||||
|
||||
def skip_without_ec2(*args, **kwargs):
|
||||
"""A decorator useful to skip tests if EC2-classic is not supported."""
|
||||
def decorator(f):
|
||||
@functools.wraps(f)
|
||||
def wrapper(self, *func_args, **func_kwargs):
|
||||
if not TesterStateHolder().get_ec2_enabled():
|
||||
msg = "Skipped because EC2-classic is not enabled"
|
||||
raise testtools.TestCase.skipException(msg)
|
||||
return f(self, *func_args, **func_kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
def skip_without_vpc(*args, **kwargs):
|
||||
"""A decorator useful to skip tests if VPC is not supported."""
|
||||
def decorator(f):
|
||||
@functools.wraps(f)
|
||||
def wrapper(self, *func_args, **func_kwargs):
|
||||
if not TesterStateHolder().get_vpc_enabled():
|
||||
msg = "Skipped because VPC is disabled"
|
||||
raise testtools.TestCase.skipException(msg)
|
||||
return f(self, *func_args, **func_kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
def check_network_feature_enabled(ext_name):
|
||||
if hasattr(CONF, 'network_feature_enabled'):
|
||||
ext_list = CONF.network_feature_enabled.api_extensions
|
||||
else:
|
||||
ext_list = ['all']
|
||||
if 'all' not in ext_list and ext_name not in ext_list:
|
||||
msg = ("Skipped network test as %s is not available" % ext_name)
|
||||
raise testtools.TestCase.skipException(msg)
|
||||
|
||||
|
||||
def skip_without_network_feature(ext_name, *args, **kwargs):
|
||||
"""A decorator useful to skip tests without specified network extension."""
|
||||
def decorator(f):
|
||||
@functools.wraps(f)
|
||||
def wrapper(self, *func_args, **func_kwargs):
|
||||
check_network_feature_enabled(ext_name)
|
||||
return f(self, *func_args, **func_kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
class EC2TestCase(base.BaseTestCase):
|
||||
"""Recommended to use as base class for boto related test."""
|
||||
|
||||
# The trash contains cleanup functions and paramaters in tuples
|
||||
# (function, *args, **kwargs)
|
||||
_global_resource_trash_bin = {}
|
||||
_global_sequence = -1
|
||||
|
||||
@classmethod
|
||||
@safe_setup
|
||||
def setUpClass(cls):
|
||||
super(EC2TestCase, cls).setUpClass()
|
||||
if not CONF.service_available.ec2api:
|
||||
raise cls.skipException("ec2api is disabled")
|
||||
|
||||
cls.client = botocoreclient.get_ec2_client(
|
||||
CONF.aws.ec2_url, CONF.aws.aws_region,
|
||||
CONF.aws.aws_access, CONF.aws.aws_secret,
|
||||
CONF.aws.ca_bundle)
|
||||
cls.s3_client = botocoreclient.get_s3_client(
|
||||
CONF.aws.s3_url, CONF.aws.aws_region,
|
||||
CONF.aws.aws_access, CONF.aws.aws_secret,
|
||||
CONF.aws.ca_bundle)
|
||||
TesterStateHolder().ec2_client = cls.client
|
||||
|
||||
@classmethod
|
||||
def addResourceCleanUpStatic(cls, function, *args, **kwargs):
|
||||
"""Adds CleanUp callable, used by tearDownClass.
|
||||
|
||||
Recommended to a use (deep)copy on the mutable args.
|
||||
"""
|
||||
tb = traceback.extract_stack(limit=2)
|
||||
cls._global_sequence = cls._global_sequence + 1
|
||||
cls._global_resource_trash_bin[cls._global_sequence] = (function,
|
||||
args, kwargs,
|
||||
tb[0])
|
||||
return cls._global_sequence
|
||||
|
||||
def setUp(self):
|
||||
super(EC2TestCase, self).setUp()
|
||||
self._resource_trash_bin = {}
|
||||
self._sequence = -1
|
||||
|
||||
def tearDown(self):
|
||||
fail_count = self.cleanUp(self._resource_trash_bin)
|
||||
super(EC2TestCase, self).tearDown()
|
||||
if fail_count:
|
||||
raise exceptions.TempestException("%d cleanUp operation failed"
|
||||
% fail_count)
|
||||
|
||||
def addResourceCleanUp(self, function, *args, **kwargs):
|
||||
"""Adds CleanUp callable, used by tearDown.
|
||||
|
||||
Recommended to a use (deep)copy on the mutable args.
|
||||
"""
|
||||
tb = traceback.extract_stack(limit=2)[0]
|
||||
self._sequence = self._sequence + 1
|
||||
self._resource_trash_bin[self._sequence] = (function, args, kwargs, tb)
|
||||
|
||||
LOG.debug("For cleaning up: %s\n From: %s" %
|
||||
(self.friendly_function_call_str(function, *args, **kwargs),
|
||||
str((tb[0], tb[1], tb[2]))))
|
||||
|
||||
return self._sequence
|
||||
|
||||
def cancelResourceCleanUp(self, key):
|
||||
"""Cancel Clean up request."""
|
||||
del self._resource_trash_bin[key]
|
||||
|
||||
# NOTE(andrey-mp): if ERROR in responce_code then treat object as deleted
|
||||
_VALID_CLEANUP_ERRORS = [
|
||||
'NotFound',
|
||||
'Gateway.NotAttached'
|
||||
]
|
||||
|
||||
# NOTE(andrey-mp): function must return boolean - should we retry
|
||||
# deleting or not
|
||||
_HOOKED_CLEANUP_ERRORS = {
|
||||
('delete_vpc', 'DependencyViolation'): (
|
||||
'delete_vpc_failed',
|
||||
lambda kwargs: kwargs['VpcId'])
|
||||
}
|
||||
|
||||
_CLEANUP_WAITERS = {
|
||||
'delete_vpc': (
|
||||
'get_vpc_waiter',
|
||||
lambda kwargs: kwargs['VpcId']),
|
||||
'delete_subnet': (
|
||||
'get_subnet_waiter',
|
||||
lambda kwargs: kwargs['SubnetId']),
|
||||
'delete_network_interface': (
|
||||
'get_network_interface_waiter',
|
||||
lambda kwargs: kwargs['NetworkInterfaceId']),
|
||||
'terminate_instances': (
|
||||
'get_instance_waiter',
|
||||
lambda kwargs: kwargs['InstanceIds'][0]),
|
||||
'delete_volume': (
|
||||
'get_volume_waiter',
|
||||
lambda kwargs: kwargs['VolumeId']),
|
||||
'detach_volume': (
|
||||
'get_volume_attachment_waiter',
|
||||
lambda kwargs: kwargs['VolumeId']),
|
||||
'delete_snapshot': (
|
||||
'get_snapshot_waiter',
|
||||
lambda kwargs: kwargs['SnapshotId']),
|
||||
'deregister_image': (
|
||||
'get_image_waiter',
|
||||
lambda kwargs: kwargs['ImageId']),
|
||||
'detach_vpn_gateway': (
|
||||
'get_vpn_gateway_attachment_waiter',
|
||||
lambda kwargs: kwargs['VpnGatewayId']),
|
||||
'delete_vpn_connection': (
|
||||
'get_vpn_connection_waiter',
|
||||
lambda kwargs: kwargs['VpnConnectionId']),
|
||||
'delete_customer_gateway': (
|
||||
'get_customer_gateway_waiter',
|
||||
lambda kwargs: kwargs['CustomerGatewayId']),
|
||||
'delete_vpn_gateway': (
|
||||
'get_vpn_gateway_waiter',
|
||||
lambda kwargs: kwargs['VpnGatewayId']),
|
||||
'disassociate_address': (
|
||||
'get_address_assoc_waiter',
|
||||
lambda kwargs: kwargs),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
fail_count = cls.cleanUp(cls._global_resource_trash_bin)
|
||||
super(EC2TestCase, cls).tearDownClass()
|
||||
if fail_count:
|
||||
raise exceptions.TempestException("%d cleanUp operation failed"
|
||||
% fail_count)
|
||||
|
||||
@classmethod
|
||||
def cleanUp(cls, trash_bin):
|
||||
"""Calls the callables added by addResourceCleanUp,
|
||||
|
||||
when you overwire this function dont't forget to call this too.
|
||||
"""
|
||||
fail_count = 0
|
||||
trash_keys = sorted(trash_bin, reverse=True)
|
||||
for key in trash_keys:
|
||||
(function, pos_args, kw_args, tb) = trash_bin[key]
|
||||
try:
|
||||
LOG.debug("Cleaning up: %s\n From: %s" %
|
||||
(cls.friendly_function_call_str(function, *pos_args,
|
||||
**kw_args),
|
||||
str((tb[0], tb[1], tb[2]))))
|
||||
res = cls.cleanUpItem(function, pos_args, kw_args)
|
||||
if not res:
|
||||
fail_count += 1
|
||||
LOG.error('Failure in cleanup for: %s' % str(kw_args))
|
||||
except BaseException:
|
||||
fail_count += 1
|
||||
LOG.exception('Failure in cleanup for: %s' % str(kw_args))
|
||||
finally:
|
||||
del trash_bin[key]
|
||||
return fail_count
|
||||
|
||||
@classmethod
|
||||
def cleanUpItem(cls, function, pos_args, kw_args):
|
||||
attempts_left = 10
|
||||
interval = 1
|
||||
deleted = False
|
||||
while not deleted and attempts_left > 0:
|
||||
try:
|
||||
function(*pos_args, **kw_args)
|
||||
deleted = True
|
||||
|
||||
key = function.__name__
|
||||
if key in cls._CLEANUP_WAITERS:
|
||||
(waiter, obj_id) = cls._CLEANUP_WAITERS[key]
|
||||
waiter = getattr(cls, waiter)
|
||||
obj_id = obj_id(kw_args)
|
||||
try:
|
||||
waiter().wait_delete(obj_id)
|
||||
except botocore.exceptions.ClientError as e:
|
||||
LOG.exception('Exception occurred in cleanup waiting')
|
||||
return False
|
||||
except botocore.exceptions.ClientError as e:
|
||||
error_code = e.response['Error']['Code']
|
||||
for err in cls._VALID_CLEANUP_ERRORS:
|
||||
if err in error_code:
|
||||
deleted = True
|
||||
break
|
||||
else:
|
||||
hook_res = False
|
||||
key = (function.__name__, error_code)
|
||||
if key in cls._HOOKED_CLEANUP_ERRORS:
|
||||
(hook, obj_id) = cls._HOOKED_CLEANUP_ERRORS[key]
|
||||
hook = getattr(cls, hook)
|
||||
obj_id = obj_id(kw_args)
|
||||
hook_res = hook(obj_id)
|
||||
if not hook_res:
|
||||
LOG.error('Cleanup failed: %s', e, exc_info=True)
|
||||
return False
|
||||
LOG.error('Retrying cleanup due to: %s', e)
|
||||
time.sleep(interval)
|
||||
attempts_left -= 1
|
||||
interval += 1
|
||||
|
||||
return deleted
|
||||
|
||||
@classmethod
|
||||
def friendly_function_name_simple(cls, call_able):
|
||||
name = ""
|
||||
if hasattr(call_able, "im_class"):
|
||||
name += call_able.im_class.__name__ + "."
|
||||
name += call_able.__name__
|
||||
return name
|
||||
|
||||
@classmethod
|
||||
def friendly_function_call_str(cls, call_able, *args, **kwargs):
|
||||
string = cls.friendly_function_name_simple(call_able)
|
||||
string += "(" + ", ".join(map(str, args))
|
||||
if len(kwargs):
|
||||
if len(args):
|
||||
string += ", "
|
||||
string += ", ".join("=".join(map(str, (key, value)))
|
||||
for (key, value) in kwargs.items())
|
||||
return string + ")"
|
||||
|
||||
@classmethod
|
||||
def _vpc_get_state(cls, vpc_id):
|
||||
try:
|
||||
data = cls.client.describe_vpcs(VpcIds=[vpc_id])
|
||||
if not data['Vpcs']:
|
||||
raise exceptions.NotFound()
|
||||
return data['Vpcs'][0]['State']
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidVpcID.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_vpc_waiter(cls):
|
||||
return EC2Waiter(cls._vpc_get_state)
|
||||
|
||||
@classmethod
|
||||
def _subnet_get_state(cls, subnet_id):
|
||||
try:
|
||||
data = cls.client.describe_subnets(SubnetIds=[subnet_id])
|
||||
if not data['Subnets']:
|
||||
raise exceptions.NotFound()
|
||||
return data['Subnets'][0]['State']
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidSubnetID.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_subnet_waiter(cls):
|
||||
return EC2Waiter(cls._subnet_get_state)
|
||||
|
||||
@classmethod
|
||||
def _address_assoc_get_state(cls, kwargs):
|
||||
try:
|
||||
ip = kwargs.get('PublicIp')
|
||||
alloc_id = kwargs.get('AllocationId')
|
||||
assoc_id = kwargs.get('AssociationId')
|
||||
if ip:
|
||||
data = cls.client.describe_addresses(PublicIps=[ip])
|
||||
elif alloc_id:
|
||||
data = cls.client.describe_addresses(AllocationIds=[alloc_id])
|
||||
elif assoc_id:
|
||||
data = cls.client.describe_addresses(
|
||||
Filters=[{'Name': 'association-id', 'Values': [assoc_id]}])
|
||||
|
||||
LOG.debug('Addresses: %s' % str(data.get('Addresses')))
|
||||
|
||||
if ('Addresses' in data and len(data['Addresses']) == 1 and
|
||||
data['Addresses'][0].get('InstanceId')):
|
||||
return 'available'
|
||||
raise exceptions.NotFound()
|
||||
except botocore.exceptions.ClientError:
|
||||
raise exceptions.NotFound()
|
||||
|
||||
@classmethod
|
||||
def get_address_assoc_waiter(cls):
|
||||
return EC2Waiter(cls._address_assoc_get_state)
|
||||
|
||||
@classmethod
|
||||
def _instance_get_state(cls, instance_id):
|
||||
try:
|
||||
data = cls.client.describe_instances(InstanceIds=[instance_id])
|
||||
if not data['Reservations']:
|
||||
raise exceptions.NotFound()
|
||||
if not data['Reservations'][0]['Instances']:
|
||||
raise exceptions.NotFound()
|
||||
state = data['Reservations'][0]['Instances'][0]['State']['Name']
|
||||
if state != 'terminated':
|
||||
return state
|
||||
raise exceptions.NotFound()
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidInstanceID.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_instance_waiter(cls):
|
||||
return EC2Waiter(cls._instance_get_state)
|
||||
|
||||
@classmethod
|
||||
def _network_interface_get_state(cls, ni_id):
|
||||
try:
|
||||
data = cls.client.describe_network_interfaces(
|
||||
NetworkInterfaceIds=[ni_id])
|
||||
if not data['NetworkInterfaces']:
|
||||
raise exceptions.NotFound()
|
||||
return data['NetworkInterfaces'][0]['Status']
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidNetworkInterfaceID.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_network_interface_waiter(cls):
|
||||
return EC2Waiter(cls._network_interface_get_state)
|
||||
|
||||
@classmethod
|
||||
def _volume_get_state(cls, volume_id):
|
||||
try:
|
||||
data = cls.client.describe_volumes(VolumeIds=[volume_id])
|
||||
if not data['Volumes']:
|
||||
raise exceptions.NotFound()
|
||||
return data['Volumes'][0]['State']
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidVolume.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_volume_waiter(cls):
|
||||
return EC2Waiter(cls._volume_get_state)
|
||||
|
||||
@classmethod
|
||||
def _volume_attachment_get_state(cls, volume_id):
|
||||
try:
|
||||
data = cls.client.describe_volumes(VolumeIds=[volume_id])
|
||||
volume = data['Volumes'][0]
|
||||
if 'Attachments' in volume and len(volume['Attachments']) > 0:
|
||||
return volume['Attachments'][0]['State']
|
||||
raise exceptions.NotFound()
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidVolume.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_volume_attachment_waiter(cls):
|
||||
return EC2Waiter(cls._volume_attachment_get_state)
|
||||
|
||||
@classmethod
|
||||
def _snapshot_get_state(cls, snapshot_id):
|
||||
try:
|
||||
data = cls.client.describe_snapshots(SnapshotIds=[snapshot_id])
|
||||
if not data['Snapshots']:
|
||||
raise exceptions.NotFound()
|
||||
return data['Snapshots'][0]['State']
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidSnapshot.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_snapshot_waiter(cls):
|
||||
return EC2Waiter(cls._snapshot_get_state)
|
||||
|
||||
@classmethod
|
||||
def _image_get_state(cls, image_id):
|
||||
try:
|
||||
data = cls.client.describe_images(ImageIds=[image_id])
|
||||
if not data['Images']:
|
||||
raise exceptions.NotFound()
|
||||
return data['Images'][0]['State']
|
||||
except botocore.exceptions.ClientError:
|
||||
error_code = sys.exc_info()[1].response['Error']['Code']
|
||||
if error_code == 'InvalidAMIID.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_image_waiter(cls):
|
||||
return EC2Waiter(cls._image_get_state)
|
||||
|
||||
@classmethod
|
||||
def _vpn_gateway_get_attachment_state(cls, vpn_gateway_id):
|
||||
try:
|
||||
data = cls.client.describe_vpn_gateways(
|
||||
VpnGatewayIds=[vpn_gateway_id])
|
||||
attachments = data['VpnGateways'][0].get('VpcAttachments')
|
||||
if (not attachments or
|
||||
attachments[0]['State'] == 'detached'):
|
||||
raise exceptions.NotFound()
|
||||
return attachments[0]['State']
|
||||
except botocore.exceptions.ClientError as ex:
|
||||
error_code = ex.response['Error']['Code']
|
||||
if error_code == 'InvalidVpnGatewayID.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_vpn_gateway_attachment_waiter(cls):
|
||||
return EC2Waiter(cls._vpn_gateway_get_attachment_state)
|
||||
|
||||
@classmethod
|
||||
def _vpn_object_get_state(cls, func, kwargs, data_key, error_not_found):
|
||||
# NOTE(andrey-mp): use this for vpn_connection, vpn_gateway,
|
||||
# customer_gateway due to similar states
|
||||
try:
|
||||
data = func(**kwargs)
|
||||
if not data[data_key]:
|
||||
raise exceptions.NotFound()
|
||||
if data[data_key][0]['State'] == 'deleted':
|
||||
raise exceptions.NotFound()
|
||||
return data[data_key][0]['State']
|
||||
except botocore.exceptions.ClientError as ex:
|
||||
error_code = ex.response['Error']['Code']
|
||||
if error_code == error_not_found:
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def _vpn_connection_get_state(cls, vpn_connection_id):
|
||||
return cls._vpn_object_get_state(
|
||||
cls.client.describe_vpn_connections,
|
||||
{'VpnConnectionIds': [vpn_connection_id]},
|
||||
'VpnConnections',
|
||||
'InvalidVpnConnectionID.NotFound')
|
||||
|
||||
@classmethod
|
||||
def get_vpn_connection_waiter(cls):
|
||||
return EC2Waiter(cls._vpn_connection_get_state)
|
||||
|
||||
@classmethod
|
||||
def _customer_gateway_get_state(cls, customer_gateway_id):
|
||||
return cls._vpn_object_get_state(
|
||||
cls.client.describe_customer_gateways,
|
||||
{'CustomerGatewayIds': [customer_gateway_id]},
|
||||
'CustomerGateways',
|
||||
'InvalidCustomerGatewayID.NotFound')
|
||||
|
||||
@classmethod
|
||||
def get_customer_gateway_waiter(cls):
|
||||
return EC2Waiter(cls._customer_gateway_get_state)
|
||||
|
||||
@classmethod
|
||||
def _vpn_gateway_get_state(cls, vpn_gateway_id):
|
||||
return cls._vpn_object_get_state(
|
||||
cls.client.describe_vpn_gateways,
|
||||
{'VpnGatewayIds': [vpn_gateway_id]},
|
||||
'VpnGateways',
|
||||
'InvalidVpnGatewayID.NotFound')
|
||||
|
||||
@classmethod
|
||||
def get_vpn_gateway_waiter(cls):
|
||||
return EC2Waiter(cls._vpn_gateway_get_state)
|
||||
|
||||
@classmethod
|
||||
def _vpn_connection_get_route_state(cls, vpn_connection_id,
|
||||
destination_cidr_block=None):
|
||||
try:
|
||||
data = cls.client.describe_vpn_connections(
|
||||
VpnConnectionIds=[vpn_connection_id])
|
||||
try:
|
||||
route = next(
|
||||
r for r in data['VpnConnections'][0]['Routes']
|
||||
if r['DestinationCidrBlock'] == destination_cidr_block)
|
||||
except StopIteration:
|
||||
raise exceptions.NotFound()
|
||||
if route['State'] == 'deleted':
|
||||
raise exceptions.NotFound()
|
||||
return route['State']
|
||||
except botocore.exceptions.ClientError as ex:
|
||||
error_code = ex.response['Error']['Code']
|
||||
if error_code == 'InvalidVpnGatewayID.NotFound':
|
||||
raise exceptions.NotFound()
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
def get_vpn_connection_route_waiter(cls, destination_cidr_block):
|
||||
return EC2Waiter(
|
||||
functools.partial(cls._vpn_connection_get_route_state,
|
||||
destination_cidr_block=destination_cidr_block))
|
||||
|
||||
@classmethod
|
||||
def _vpn_connection_get_tunnel_up_state(cls, vpn_connection_id):
|
||||
data = cls.client.describe_vpn_connections(
|
||||
VpnConnectionIds=[vpn_connection_id])
|
||||
for item in data['VpnConnections'][0].get('VgwTelemetry', []):
|
||||
if 'UP' == item['Status']:
|
||||
return 'UP'
|
||||
raise exceptions.NotFound()
|
||||
|
||||
@classmethod
|
||||
def get_vpn_connection_tunnel_waiter(cls):
|
||||
return EC2Waiter(cls._vpn_connection_get_tunnel_up_state)
|
||||
|
||||
@classmethod
|
||||
def delete_vpc_failed(cls, vpc_id):
|
||||
try:
|
||||
LOG.warning('VpnGateways: ' +
|
||||
str(cls.client.describe_vpn_gateways(
|
||||
Filters=[{'Name': 'attachment.vpc-id', 'Values': [vpc_id]}]
|
||||
)['VpnGateways']))
|
||||
LOG.warning('RouteTables: ' +
|
||||
str(cls.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}]
|
||||
)['RouteTables']))
|
||||
return True
|
||||
except Exception:
|
||||
LOG.exception('Error occurred during "delete_vpc_failed" hook')
|
||||
return False
|
||||
|
||||
def assertEmpty(self, list_obj, msg=None):
|
||||
self.assertTrue(len(list_obj) == 0, msg)
|
||||
|
||||
def assertNotEmpty(self, list_obj, msg=None):
|
||||
self.assertTrue(len(list_obj) > 0, msg)
|
||||
|
||||
def assertRaises(self, error_code, fn, rollback_fn=None, **kwargs):
|
||||
try:
|
||||
fn_data = fn(**kwargs)
|
||||
if rollback_fn:
|
||||
try:
|
||||
rollback_fn(fn_data)
|
||||
except Exception:
|
||||
LOG.exception('Rollback failed')
|
||||
msg = ("%s hasn't returned exception for params %s"
|
||||
% (str(fn.__name__), str(kwargs)))
|
||||
raise self.failureException(msg)
|
||||
except botocore.exceptions.ClientError as e:
|
||||
self.assertEqual(error_code, e.response['Error']['Code'])
|
||||
|
||||
# NOTE(andrey-mp): Helpers zone
|
||||
|
||||
def get_instance(self, instance_id):
|
||||
data = self.client.describe_instances(InstanceIds=[instance_id])
|
||||
self.assertEqual(1, len(data.get('Reservations', [])))
|
||||
instances = data['Reservations'][0].get('Instances', [])
|
||||
self.assertEqual(1, len(instances))
|
||||
return instances[0]
|
||||
|
||||
def get_instance_bdm(self, instance_id, device_name):
|
||||
"""
|
||||
|
||||
device_name=None means getting bdm of root instance device
|
||||
"""
|
||||
instance = self.get_instance(instance_id)
|
||||
if not device_name:
|
||||
device_name = instance.get('RootDeviceName')
|
||||
if not device_name:
|
||||
return None
|
||||
bdms = instance.get('BlockDeviceMappings')
|
||||
if bdms is None:
|
||||
return None
|
||||
bdt = [bdt for bdt in bdms if bdt['DeviceName'] == device_name]
|
||||
return None if len(bdt) == 0 else bdt[0]
|
||||
|
||||
def run_instance(self, clean_dict=None, **kwargs):
|
||||
kwargs.setdefault('ImageId', CONF.aws.image_id)
|
||||
kwargs.setdefault('InstanceType', CONF.aws.instance_type)
|
||||
kwargs.setdefault('Placement', {'AvailabilityZone': CONF.aws.aws_zone})
|
||||
kwargs['MinCount'] = 1
|
||||
kwargs['MaxCount'] = 1
|
||||
data = self.client.run_instances(*[], **kwargs)
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
if clean_dict is not None:
|
||||
clean_dict['instance'] = res_clean
|
||||
|
||||
return instance_id
|
||||
|
||||
def create_vpc_and_subnet(self, cidr):
|
||||
data = self.client.create_vpc(CidrBlock=cidr)
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
self.addResourceCleanUp(self.client.delete_vpc, VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
data = self.client.create_subnet(VpcId=vpc_id, CidrBlock=cidr,
|
||||
AvailabilityZone=CONF.aws.aws_zone)
|
||||
subnet_id = data['Subnet']['SubnetId']
|
||||
self.addResourceCleanUp(self.client.delete_subnet, SubnetId=subnet_id)
|
||||
|
||||
return vpc_id, subnet_id
|
||||
|
||||
def prepare_route(self, vpc_id, gw_id):
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])
|
||||
self.assertEqual(1, len(data['RouteTables']))
|
||||
route_table_id = data['RouteTables'][0]['RouteTableId']
|
||||
|
||||
kwargs = {
|
||||
'DestinationCidrBlock': '0.0.0.0/0',
|
||||
'RouteTableId': route_table_id,
|
||||
'GatewayId': gw_id
|
||||
}
|
||||
self.client.create_route(*[], **kwargs)
|
||||
|
||||
return route_table_id
|
||||
|
||||
def create_and_attach_internet_gateway(self, vpc_id):
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
self.addResourceCleanUp(self.client.delete_internet_gateway,
|
||||
InternetGatewayId=gw_id)
|
||||
data = self.client.attach_internet_gateway(VpcId=vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
self.addResourceCleanUp(self.client.detach_internet_gateway,
|
||||
VpcId=vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
|
||||
return gw_id
|
|
@ -1,89 +0,0 @@
|
|||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging as std_logging
|
||||
import os
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from ec2api.tests.functional import config_opts
|
||||
|
||||
|
||||
LOG = logging.getLogger('ec2api')
|
||||
|
||||
|
||||
# this should never be called outside of this class
|
||||
class ConfigPrivate(object):
|
||||
"""Provides OpenStack configuration information."""
|
||||
|
||||
DEFAULT_CONFIG_FILE = "functional_tests.conf"
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize a configuration from a conf directory and conf file."""
|
||||
super(ConfigPrivate, self).__init__()
|
||||
|
||||
# if this was run from tempest runner then config already parsed
|
||||
if config_opts.aws_group.name in cfg.CONF:
|
||||
self.aws = cfg.CONF.aws
|
||||
self.service_available = cfg.CONF.service_available
|
||||
self.network_feature_enabled = cfg.CONF['network-feature-enabled']
|
||||
return
|
||||
|
||||
# Environment variables override defaults...
|
||||
conf_file = os.environ.get('TEST_CONFIG', self.DEFAULT_CONFIG_FILE)
|
||||
conf_dirs = list()
|
||||
if os.environ.get('TEST_CONFIG_DIR'):
|
||||
conf_dirs.append(os.environ.get('TEST_CONFIG_DIR'))
|
||||
conf_dirs.append('.')
|
||||
conf_dirs.append(os.path.dirname(os.path.dirname(
|
||||
os.path.dirname(os.path.dirname(__file__)))))
|
||||
for _dir in conf_dirs:
|
||||
path = os.path.join(_dir, conf_file)
|
||||
if os.path.isfile(path):
|
||||
break
|
||||
else:
|
||||
raise Exception('Config could not be found')
|
||||
|
||||
LOG.info("Using ec2api config file %s" % path)
|
||||
conf = cfg.CONF
|
||||
conf([], project='ec2api', default_config_files=[path])
|
||||
|
||||
conf.register_group(config_opts.aws_group)
|
||||
group_name = config_opts.aws_group.name
|
||||
for opt in config_opts.AWSGroup:
|
||||
conf.register_opt(opt, group=group_name)
|
||||
self.aws = cfg.CONF.aws
|
||||
|
||||
conf.register_group(config_opts.service_available_group)
|
||||
group_name = config_opts.service_available_group.name
|
||||
for opt in config_opts.ServiceAvailableGroup:
|
||||
conf.register_opt(opt, group=group_name)
|
||||
self.service_available = cfg.CONF.service_available
|
||||
|
||||
conf.log_opt_values(LOG, std_logging.DEBUG)
|
||||
|
||||
|
||||
class ConfigProxy(object):
|
||||
_config = None
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if not self._config:
|
||||
self._config = ConfigPrivate()
|
||||
|
||||
return getattr(self._config, attr)
|
||||
|
||||
|
||||
CONF = ConfigProxy()
|
|
@ -1,96 +0,0 @@
|
|||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
service_available_group = cfg.OptGroup(name="service_available",
|
||||
title="Available OpenStack Services")
|
||||
|
||||
ServiceAvailableGroup = [
|
||||
cfg.BoolOpt("ec2api",
|
||||
default=True,
|
||||
help="Whether or not ec2-api is expected to be available"),
|
||||
]
|
||||
|
||||
|
||||
aws_group = cfg.OptGroup(name='aws',
|
||||
title='AWS options')
|
||||
AWSGroup = [
|
||||
cfg.StrOpt('ec2_url',
|
||||
default="http://localhost:8788/",
|
||||
help="EC2 URL"),
|
||||
cfg.StrOpt('s3_url',
|
||||
default="http://localhost:3334/",
|
||||
help="S3 URL"),
|
||||
cfg.StrOpt('ca_bundle',
|
||||
default=None,
|
||||
help="The CA certificate bundle to use when verifying "
|
||||
"SSL certificates. Or True/False to pass to botocore."),
|
||||
cfg.StrOpt('aws_secret',
|
||||
default=None,
|
||||
help="AWS Secret Key",
|
||||
secret=True),
|
||||
cfg.StrOpt('aws_access',
|
||||
default=None,
|
||||
help="AWS Access Key"),
|
||||
cfg.StrOpt('aws_region',
|
||||
default="RegionOne",
|
||||
help="AWS region for EC2 tests"),
|
||||
cfg.StrOpt('aws_zone',
|
||||
default='nova',
|
||||
help="AWS zone inside region for EC2 tests"),
|
||||
cfg.IntOpt('build_timeout',
|
||||
default=120,
|
||||
help="Status Change Timeout"),
|
||||
cfg.IntOpt('build_interval',
|
||||
default=1,
|
||||
help="Status Change Test Interval"),
|
||||
cfg.StrOpt('instance_type',
|
||||
default="m1.tiny",
|
||||
help="Instance type"),
|
||||
cfg.StrOpt('instance_type_alt',
|
||||
default=None,
|
||||
help="Instance type"),
|
||||
cfg.StrOpt('image_id',
|
||||
default=None,
|
||||
help="Image ID for instance running(can be cirros). "
|
||||
"It must be any instance with instance-store "
|
||||
"root device type."),
|
||||
cfg.StrOpt('ebs_image_id',
|
||||
default=None,
|
||||
help="EBS Image ID for testing snapshots, volumes, instances."),
|
||||
cfg.StrOpt('image_user',
|
||||
default='cirros',
|
||||
help="User for sshing into instance based on configured image"),
|
||||
cfg.StrOpt('image_id_ubuntu',
|
||||
default=None,
|
||||
help="Fully functional image ID for instance running. "
|
||||
"For some tests it must be ubuntu-trusty-i386."),
|
||||
cfg.StrOpt('image_user_ubuntu',
|
||||
default='ubuntu',
|
||||
help="User for sshing into instance based on configured image"),
|
||||
cfg.BoolOpt('run_incompatible_tests',
|
||||
default=False,
|
||||
help='Will run all tests plus incompatible with Amazon.'),
|
||||
cfg.BoolOpt('run_long_tests',
|
||||
default=False,
|
||||
help='Will run all long tests also.'),
|
||||
cfg.StrOpt('ami_image_location',
|
||||
default=None,
|
||||
help="S3 URL with manifest of AMI Machine Image."),
|
||||
cfg.BoolOpt('run_ssh',
|
||||
default=True,
|
||||
help='Can block all tests that wants to ssh into instance.'),
|
||||
]
|
|
@ -1,86 +0,0 @@
|
|||
# Copyright 2014
|
||||
# The Cloudscaling Group, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import ConfigParser
|
||||
import functools
|
||||
import os
|
||||
|
||||
import testtools
|
||||
|
||||
import tempest.test
|
||||
|
||||
|
||||
def skip(*args, **kwargs):
|
||||
"""A decorator useful to skip tests with message."""
|
||||
def decorator(f):
|
||||
@functools.wraps(f)
|
||||
def wrapper(*func_args, **func_kwargs):
|
||||
if "bug" in kwargs:
|
||||
msg = "Skipped until Bug %s is resolved." % kwargs["bug"]
|
||||
else:
|
||||
msg = kwargs["msg"]
|
||||
raise testtools.TestCase.skipException(msg)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
class TestCasePreparationError(Exception):
|
||||
def __init__(self, msg="Error in test case preparation"):
|
||||
self.msg = msg
|
||||
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
|
||||
class BaseTest(tempest.test.BaseTestCase):
|
||||
"""Base class for Cloudscaling tests"""
|
||||
pass
|
||||
|
||||
|
||||
class BaseBenchmarkTest(BaseTest):
|
||||
"""Base class for Cloudscaling tests"""
|
||||
|
||||
@classmethod
|
||||
def _load_benchmark_data(cls, class_name):
|
||||
cfg = cls.config.cloudscaling
|
||||
if not cfg.benchmark_data:
|
||||
return None
|
||||
|
||||
config = ConfigParser.ConfigParser()
|
||||
f = open(os.path.expanduser(cfg.benchmark_data))
|
||||
config.readfp(f)
|
||||
f.close()
|
||||
items = config.items(class_name)
|
||||
result_items = {}
|
||||
for item in items:
|
||||
boundaries = item[1].split("-")
|
||||
if len(boundaries) == 2:
|
||||
result_items[item[0]] = (boundaries[0], boundaries[1])
|
||||
|
||||
cls.benchmark_data = result_items
|
||||
|
||||
def _get_benchmark_data(self):
|
||||
return self.benchmark_data
|
||||
|
||||
def _get_benchmark_result(self, result_name=None):
|
||||
if not hasattr(self, 'benchmark_data'):
|
||||
return None
|
||||
|
||||
key = self._testMethodName.lower()
|
||||
if result_name is not None:
|
||||
key += "." + result_name
|
||||
if key in self.benchmark_data:
|
||||
return self.benchmark_data[key]
|
||||
|
||||
return None
|
|
@ -1,361 +0,0 @@
|
|||
# Copyright 2014
|
||||
# The Cloudscaling Group, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import fnmatch
|
||||
|
||||
from boto import exception as boto_exception
|
||||
import netaddr
|
||||
|
||||
from tempest import auth
|
||||
from tempest import clients as base_clients
|
||||
from tempest.cloudscaling import base
|
||||
from tempest.cloudscaling.thirdparty.scenario.aws_compat import clients
|
||||
from tempest import config
|
||||
from tempest import exceptions
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest import test as base_test
|
||||
from tempest.thirdparty.boto import test
|
||||
from tempest.thirdparty.boto.utils import wait as boto_wait
|
||||
|
||||
|
||||
VOLUME_SIZE = 1
|
||||
|
||||
|
||||
class BaseAWSTest(base.BaseTest, test.BotoTestCase):
|
||||
"""Base class for AWS compat Cloudscaling tests"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(BaseAWSTest, cls).setUpClass()
|
||||
|
||||
cls.os = clients.Manager()
|
||||
cls.ec2_client = cls.os.ec2api_client
|
||||
cls.vpc_client = cls.os.vpc_client
|
||||
|
||||
cls.config = config.CONF
|
||||
cls.instance_type = cls.config.boto.instance_type
|
||||
|
||||
@classmethod
|
||||
def _processException(cls, exc):
|
||||
if isinstance(exc, boto_exception.EC2ResponseError):
|
||||
value = getattr(exc, "message", None)
|
||||
if not value:
|
||||
value = getattr(exc, "error_message", None)
|
||||
msg = str(exc.error_code) + ": " + str(value)
|
||||
return (base_test.TestResultLabel.ERROR, msg)
|
||||
return super(BaseAWSTest, cls)._processException(exc)
|
||||
|
||||
@classmethod
|
||||
def _prepare_image_id(cls, image_name):
|
||||
"""Searches existing available image ID by given name pattern"""
|
||||
|
||||
images = cls.ec2_client.get_all_images(filters={
|
||||
"name": image_name,
|
||||
"image-type": "machine",
|
||||
"is-public": "true"})
|
||||
# NOTE(apavlov) There is no filtering in nova-api-ec2. Filter here.
|
||||
filtered_images = []
|
||||
for image in images:
|
||||
if not fnmatch.fnmatch(image.name, image_name):
|
||||
continue
|
||||
if image.type != "machine":
|
||||
continue
|
||||
if not image.is_public:
|
||||
continue
|
||||
filtered_images.append(image)
|
||||
if len(filtered_images) > 0:
|
||||
return filtered_images[0].id
|
||||
|
||||
return image_name
|
||||
|
||||
@classmethod
|
||||
def _prepare_key_pair(cls):
|
||||
"""Key-pair preparation"""
|
||||
|
||||
keypair_name = data_utils.rand_name("keypair-")
|
||||
keypair = cls.ec2_client.create_key_pair(keypair_name)
|
||||
if keypair is None or keypair.name is None:
|
||||
raise base.TestCasePreparationError("Can`t create keypair")
|
||||
cls.addResourceCleanUp(cls.ec2_client.delete_key_pair,
|
||||
keypair_name)
|
||||
return keypair
|
||||
|
||||
@classmethod
|
||||
def _prepare_security_group(cls):
|
||||
"""Security-group preparation"""
|
||||
|
||||
sec_group_name = data_utils.rand_name("securitygroup-")
|
||||
group_desc = sec_group_name + " security group description "
|
||||
security_group = cls.ec2_client.create_security_group(
|
||||
sec_group_name, group_desc)
|
||||
if security_group is None or security_group.name is None:
|
||||
raise base.TestCasePreparationError("Can't create security group")
|
||||
cls.addResourceCleanUp(cls.destroy_security_group_wait,
|
||||
security_group)
|
||||
result = cls.ec2_client.authorize_security_group(
|
||||
sec_group_name,
|
||||
ip_protocol="icmp",
|
||||
cidr_ip="0.0.0.0/0",
|
||||
from_port=-1,
|
||||
to_port=-1)
|
||||
if not result:
|
||||
raise base.TestCasePreparationError(
|
||||
"Can`t authorize security group")
|
||||
|
||||
result = cls.ec2_client.authorize_security_group(
|
||||
sec_group_name,
|
||||
ip_protocol="tcp",
|
||||
cidr_ip="0.0.0.0/0",
|
||||
from_port=22,
|
||||
to_port=22)
|
||||
if not result:
|
||||
raise base.TestCasePreparationError(
|
||||
"Can`t authorize security group")
|
||||
return security_group
|
||||
|
||||
@classmethod
|
||||
def _destroy_security_group_wait(cls, group):
|
||||
def _delete():
|
||||
cls.ec2_client.delete_security_group(group_id=group.id)
|
||||
|
||||
boto_wait.wait_no_exception(_delete)
|
||||
|
||||
@classmethod
|
||||
def _destroy_internet_gateway(cls, internet_gateway):
|
||||
igs = cls.vpc_client.get_all_internet_gateways(
|
||||
internet_gateway_ids=[internet_gateway.id])
|
||||
if len(igs) == 0:
|
||||
return
|
||||
ig = igs[0]
|
||||
for attachment in ig.attachments:
|
||||
cls.vpc_client.detach_internet_gateway(ig.id, attachment.vpc_id)
|
||||
cls.vpc_client.delete_internet_gateway(ig.id)
|
||||
|
||||
@classmethod
|
||||
def _delete_subnet_wait(cls, subnet):
|
||||
def _delete():
|
||||
cls.vpc_client.delete_subnet(subnet.id)
|
||||
|
||||
boto_wait.wait_no_exception(_delete)
|
||||
|
||||
@classmethod
|
||||
def _prepare_public_ip(cls, instance, network_interface_id=None):
|
||||
"""Public IP preparation"""
|
||||
|
||||
ip_address = instance.ip_address
|
||||
|
||||
if ip_address is None or ip_address == instance.private_ip_address:
|
||||
domain = "vpc" if instance.vpc_id is not None else None
|
||||
address = cls.ec2_client.allocate_address(domain)
|
||||
if address is None or not address.public_ip:
|
||||
raise base.TestCasePreparationError(
|
||||
"Can't allocate public IP")
|
||||
if domain is None:
|
||||
# NOTE(ft): this is temporary workaround for OS
|
||||
# it must be removed after VPC integration
|
||||
cls.addResourceCleanUp(address.delete)
|
||||
status = address.associate(instance.id)
|
||||
if not status:
|
||||
raise base.TestCasePreparationError(
|
||||
"Can't associate IP with instance")
|
||||
cls.addResourceCleanUp(address.disassociate)
|
||||
else:
|
||||
cls.addResourceCleanUp(cls.ec2_client.release_address,
|
||||
allocation_id=address.allocation_id)
|
||||
if network_interface_id:
|
||||
status = cls.ec2_client.associate_address(
|
||||
allocation_id=address.allocation_id,
|
||||
network_interface_id=network_interface_id)
|
||||
else:
|
||||
status = cls.ec2_client.associate_address(
|
||||
instance.id, allocation_id=address.allocation_id)
|
||||
if not status:
|
||||
raise base.TestCasePreparationError(
|
||||
"Can't associate IP with instance")
|
||||
addresses = cls.ec2_client.get_all_addresses(
|
||||
allocation_ids=[address.allocation_id])
|
||||
if addresses is None or len(addresses) != 1:
|
||||
raise base.TestCasePreparationError(
|
||||
"Can't get address by allocation_id")
|
||||
address = addresses[0]
|
||||
cls.addResourceCleanUp(cls.ec2_client.disassociate_address,
|
||||
association_id=address.association_id)
|
||||
instance.update()
|
||||
ip_address = address.public_ip
|
||||
|
||||
return ip_address
|
||||
|
||||
@classmethod
|
||||
def _wait_instance_state(cls, instance, final_set):
|
||||
if not isinstance(final_set, set):
|
||||
final_set = set((final_set,))
|
||||
final_set |= cls.gone_set
|
||||
lfunction = cls.get_lfunction_gone(instance)
|
||||
state = boto_wait.state_wait(lfunction, final_set,
|
||||
cls.valid_instance_state)
|
||||
if state not in final_set:
|
||||
raise base.TestCasePreparationError("Error in waiting for "
|
||||
"instance(state = '%s')" % state)
|
||||
|
||||
@classmethod
|
||||
def _correct_ns_if_needed(cls, ssh):
|
||||
try:
|
||||
ssh.exec_command("host www.com")
|
||||
except exceptions.SSHExecCommandFailed:
|
||||
# NOTE(apavlov) update nameservers (mandatory for local devstack)
|
||||
ssh.exec_command("sudo su -c 'echo nameserver 8.8.8.8 "
|
||||
"> /etc/resolv.conf'")
|
||||
ssh.exec_command("host www.com")
|
||||
|
||||
@classmethod
|
||||
def _prepare_ebs_image(cls):
|
||||
if cls.config.cloudscaling.ebs_image_id:
|
||||
return cls.config.cloudscaling.ebs_image_id
|
||||
|
||||
if not cls.config.cloudscaling.image_id_ami:
|
||||
raise cls.skipException("".join(("EC2 ", cls.__name__,
|
||||
": requires image_id_ami setting")))
|
||||
|
||||
if not cls.config.service_available.cinder:
|
||||
skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
|
||||
raise cls.skipException(skip_msg)
|
||||
if not cls.config.service_available.nova:
|
||||
skip_msg = ("%s skipped as nova is not available" % cls.__name__)
|
||||
raise cls.skipException(skip_msg)
|
||||
|
||||
admin_creds = auth.get_default_credentials('compute_admin')
|
||||
os = base_clients.Manager(admin_creds, interface='json')
|
||||
cls.os = os
|
||||
cls.volumes_client = os.volumes_client
|
||||
cls.servers_client = os.servers_client
|
||||
cls.images_client = os.images_client
|
||||
cls.snapshots_client = os.snapshots_client
|
||||
|
||||
# NOTE(apavlov): create volume
|
||||
resp, volume = cls.volumes_client.create_volume(VOLUME_SIZE,
|
||||
display_name="aws_volume")
|
||||
assert 200 == resp.status
|
||||
cls.addResourceCleanUp(cls._delete_volume, volume['id'])
|
||||
cls.volumes_client.wait_for_volume_status(volume['id'], 'available')
|
||||
|
||||
# NOTE(apavlov): boot instance
|
||||
bdm = [{
|
||||
"volume_id": volume['id'],
|
||||
"delete_on_termination": "1",
|
||||
"device_name": "/dev/vda"}]
|
||||
resp, server = cls.servers_client.create_server(
|
||||
"aws_instance",
|
||||
cls.config.cloudscaling.image_id_ami,
|
||||
cls.config.compute.flavor_ref,
|
||||
block_device_mapping=bdm)
|
||||
assert 202 == resp.status
|
||||
rc_server = cls.addResourceCleanUp(cls.servers_client.delete_server,
|
||||
server['id'])
|
||||
cls.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
|
||||
# NOTE(apavlov): create image from instance
|
||||
image_name = data_utils.rand_name("aws_ebs_image-")
|
||||
resp, _ = cls.images_client.create_image(server['id'],
|
||||
image_name)
|
||||
assert 202 == resp.status
|
||||
cls.image_id = resp["location"].split('/')[-1]
|
||||
cls.addResourceCleanUp(cls.images_client.delete_image,
|
||||
cls.image_id)
|
||||
# NOTE(apavlov): delete instance
|
||||
cls.cancelResourceCleanUp(rc_server)
|
||||
cls.servers_client.delete_server(server['id'])
|
||||
cls.servers_client.wait_for_server_termination(server['id'])
|
||||
|
||||
images = cls.ec2_client.get_all_images()
|
||||
for image in images:
|
||||
if image_name in image.location:
|
||||
return image.id
|
||||
|
||||
raise base.TestCasePreparationError("Can't find ebs image.")
|
||||
|
||||
@classmethod
|
||||
def _delete_volume(cls, volume_id):
|
||||
resp, result = cls.snapshots_client.list_snapshots(
|
||||
{"volume_id": volume_id})
|
||||
if 200 == resp.status:
|
||||
for snapshot in result:
|
||||
cls.snapshots_client.delete_snapshot(snapshot['id'])
|
||||
cls.snapshots_client.wait_for_resource_deletion(snapshot['id'])
|
||||
cls.volumes_client.delete_volume(volume_id)
|
||||
|
||||
|
||||
class BaseVPCTest(BaseAWSTest):
|
||||
"""Base class for AWS VPC behavior tests."""
|
||||
|
||||
@classmethod
|
||||
@base_test.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(BaseVPCTest, cls).setUpClass()
|
||||
cls.zone = cls.config.boto.aws_zone
|
||||
cfg = cls.config.cloudscaling
|
||||
cls.ssh_user = cfg.general_ssh_user_name
|
||||
cls.vpc_cidr = netaddr.IPNetwork(cfg.vpc_cidr)
|
||||
(cls.subnet_cidr,) = cls.vpc_cidr.subnet(cfg.vpc_subnet_prefix, 1)
|
||||
cls.image_id = cls._prepare_image_id(cfg.general_image_name)
|
||||
cls.keypair = cls._prepare_key_pair()
|
||||
|
||||
@classmethod
|
||||
def _tune_vpc(cls, vpc):
|
||||
ig = cls.vpc_client.create_internet_gateway()
|
||||
if ig is None or not ig.id:
|
||||
raise base.TestCasePreparationError()
|
||||
cls.addResourceCleanUp(cls._destroy_internet_gateway, ig)
|
||||
status = cls.vpc_client.attach_internet_gateway(ig.id, vpc.id)
|
||||
if not status:
|
||||
raise base.TestCasePreparationError()
|
||||
rtables = cls.vpc_client.get_all_route_tables(
|
||||
filters=[("vpc-id", vpc.id)])
|
||||
if rtables is None or len(rtables) != 1:
|
||||
raise base.TestCasePreparationError()
|
||||
status = cls.vpc_client.create_route(rtables[0].id, "0.0.0.0/0",
|
||||
gateway_id=ig.id)
|
||||
if not status:
|
||||
raise base.TestCasePreparationError()
|
||||
secgroups = cls.vpc_client.get_all_security_groups(
|
||||
filters={"vpc-id": vpc.id})
|
||||
if secgroups is None or len(secgroups) != 1:
|
||||
raise base.TestCasePreparationError()
|
||||
status = cls.vpc_client.authorize_security_group(
|
||||
group_id=secgroups[0].id, ip_protocol="-1",
|
||||
from_port=-1, to_port=-1, cidr_ip="0.0.0.0/0")
|
||||
if not status:
|
||||
raise base.TestCasePreparationError()
|
||||
|
||||
@classmethod
|
||||
def _prepare_vpc(cls, vpc_cidr, sn_cidr):
|
||||
# NOTE(Alex) The following code is introduced for OpenStack
|
||||
# and potentially requires fix in boto. See details in
|
||||
# test_vpc_nat_scenario.
|
||||
dhcp_opts = cls.vpc_client.create_dhcp_options(
|
||||
domain_name_servers=['8.8.8.8'])
|
||||
if dhcp_opts is None or not dhcp_opts.id:
|
||||
raise base.TestCasePreparationError()
|
||||
cls.addResourceCleanUp(cls.vpc_client.delete_dhcp_options,
|
||||
dhcp_opts.id)
|
||||
vpc = cls.vpc_client.create_vpc(str(vpc_cidr))
|
||||
if vpc is None or not vpc.id:
|
||||
raise base.TestCasePreparationError()
|
||||
cls.addResourceCleanUp(cls.vpc_client.delete_vpc, vpc.id)
|
||||
if not cls.vpc_client.associate_dhcp_options(dhcp_opts.id, vpc.id):
|
||||
raise base.TestCasePreparationError()
|
||||
cls._tune_vpc(vpc)
|
||||
sn = cls.vpc_client.create_subnet(vpc.id, str(sn_cidr), cls.zone)
|
||||
if sn is None or not sn.id:
|
||||
raise base.TestCasePreparationError()
|
||||
cls.addResourceCleanUp(cls._delete_subnet_wait, sn)
|
||||
return sn
|
|
@ -1,225 +0,0 @@
|
|||
# Copyright 2014
|
||||
# The Cloudscaling Group, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import tempest.cloudscaling.thirdparty.scenario.aws_compat.base as aws_base
|
||||
import tempest.cloudscaling.utils as utils
|
||||
from tempest.lib.common.utils.linux import remote_client
|
||||
from tempest import test
|
||||
from tempest.thirdparty.boto.utils import wait as boto_wait
|
||||
|
||||
import logging
|
||||
logging.getLogger('boto').setLevel(logging.CRITICAL)
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class InstanceMySQLTest(aws_base.BaseAWSTest):
|
||||
"""
|
||||
Test 'Running MySQL on Amazon' (http://aws.amazon.com/articles/1663)
|
||||
"""
|
||||
@classmethod
|
||||
@test.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(InstanceMySQLTest, cls).setUpClass()
|
||||
|
||||
cfg = cls.config.cloudscaling
|
||||
image_name = cfg.mysql_image_name
|
||||
cls.ssh_user = cfg.mysql_ssh_user_name
|
||||
cls.volume_attach_name = "sdh"
|
||||
|
||||
cls.image_id = cls._prepare_image_id(image_name)
|
||||
|
||||
cls.keypair = cls._prepare_key_pair()
|
||||
sg = cls._prepare_security_group()
|
||||
cls.sec_group_name = sg.name
|
||||
|
||||
def test_integration_mysql(self):
|
||||
"""Test based on http://aws.amazon.com/articles/1663"""
|
||||
|
||||
snapshot = self._run_scenario(self._create_mysql_db)
|
||||
|
||||
self._run_scenario(self._restore_mysql_db, snapshot=snapshot)
|
||||
|
||||
def _run_scenario(self, scenario_func, snapshot=None):
|
||||
# NOTE(apavlov): ec2-run-instances --key KEYPAIR IMAGE
|
||||
reservation = self.ec2_client.run_instances(self.image_id,
|
||||
instance_type=self.instance_type,
|
||||
key_name=self.keypair.name,
|
||||
security_groups=(self.sec_group_name,))
|
||||
self.addResourceCleanUp(self.destroy_reservation, reservation)
|
||||
instance = reservation.instances[0]
|
||||
LOG.info("state: %s", instance.state)
|
||||
# NOTE(apavlov): wait until it runs (ec2-describe-instances INSTANCE)
|
||||
if instance.state != "running":
|
||||
self.assertInstanceStateWait(instance, "running")
|
||||
|
||||
# NOTE(apavlov): ec2-create-volume -z ZONE -s SIZE_GB
|
||||
zone = instance.placement
|
||||
volume = self.ec2_client.create_volume(1, zone, snapshot=snapshot)
|
||||
self.addResourceCleanUp(self.destroy_volume_wait, volume)
|
||||
# NOTE(apavlov): wait it (ec2-describe-volumes VOLUME)
|
||||
self.assertVolumeStatusWait(volume, "available")
|
||||
|
||||
ip_address = self._prepare_public_ip(instance)
|
||||
ssh = remote_client.RemoteClient(ip_address,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
|
||||
# NOTE(apavlov): ec2-attach-volume -d /dev/XXX -i INSTANCE VOLUME
|
||||
# and wait until it will be available
|
||||
part_lines = ssh.get_partitions().split('\n')
|
||||
volume.attach(instance.id, "/dev/" + self.volume_attach_name)
|
||||
|
||||
def _volume_state():
|
||||
volume.update(validate=True)
|
||||
return volume.status
|
||||
|
||||
self.assertVolumeStatusWait(_volume_state, "in-use")
|
||||
boto_wait.re_search_wait(_volume_state, "in-use")
|
||||
|
||||
def _part_state():
|
||||
current = ssh.get_partitions().split('\n')
|
||||
if len(current) > len(part_lines):
|
||||
return 1
|
||||
if len(current) < len(part_lines):
|
||||
return -1
|
||||
return 0
|
||||
|
||||
boto_wait.state_wait(_part_state, 1)
|
||||
part_lines_new = ssh.get_partitions().split('\n')
|
||||
self.volume_name = utils.detect_new_volume(part_lines, part_lines_new)
|
||||
part_lines = part_lines_new
|
||||
|
||||
self._correct_ns_if_needed(ssh)
|
||||
|
||||
snapshot = scenario_func(ssh, volume.id)
|
||||
|
||||
# NOTE(apavlov): stop this instance(imagine that it will be used)
|
||||
instance.stop()
|
||||
LOG.info("state: %s", instance.state)
|
||||
if instance.state != "stopped":
|
||||
self.assertInstanceStateWait(instance, "stopped")
|
||||
|
||||
return snapshot
|
||||
|
||||
def _create_mysql_db(self, ssh, volume_id):
|
||||
ssh.exec_command("sudo apt-get update && sudo apt-get upgrade -fy")
|
||||
|
||||
# install mysql
|
||||
ssh.exec_command("echo mysql-server-5.1 mysql-server/"
|
||||
"root_password password rootpass | sudo debconf-set-selections"
|
||||
"&& echo mysql-server-5.1 mysql-server/"
|
||||
"root_password_again password rootpass "
|
||||
"| sudo debconf-set-selections"
|
||||
"&& echo mysql-server-5.1 mysql-server/"
|
||||
"start_on_boot boolean true | sudo debconf-set-selections")
|
||||
ssh.exec_command("sudo apt-get install -y xfsprogs mysql-server")
|
||||
|
||||
ssh.exec_command("grep -q xfs /proc/filesystems || sudo modprobe xfs")
|
||||
ssh.exec_command("sudo mkfs.xfs /dev/" + self.volume_name)
|
||||
ssh.exec_command("echo '/dev/" + self.volume_name
|
||||
+ " /vol xfs noatime 0 0' "
|
||||
"| sudo tee -a /etc/fstab")
|
||||
ssh.exec_command("sudo mkdir -m 000 /vol && sudo mount /vol")
|
||||
|
||||
# NOTE(apavlov): Move the existing database files to the EBS volume.
|
||||
ssh.exec_command("sudo /etc/init.d/mysql stop"
|
||||
"&& sudo mkdir /vol/etc /vol/lib /vol/log"
|
||||
"&& sudo mv /etc/mysql /vol/etc/"
|
||||
"&& sudo mv /var/lib/mysql /vol/lib/"
|
||||
"&& sudo mv /var/log/mysql /vol/log/")
|
||||
|
||||
ssh.exec_command("sudo mkdir /etc/mysql"
|
||||
"&& sudo mkdir /var/lib/mysql"
|
||||
"&& sudo mkdir /var/log/mysql")
|
||||
|
||||
ssh.exec_command("echo '/vol/etc/mysql /etc/mysql none bind' "
|
||||
"| sudo tee -a /etc/fstab"
|
||||
"&& sudo mount /etc/mysql")
|
||||
|
||||
ssh.exec_command("echo '/vol/lib/mysql /var/lib/mysql none bind' "
|
||||
"| sudo tee -a /etc/fstab"
|
||||
"&& sudo mount /var/lib/mysql")
|
||||
|
||||
ssh.exec_command("echo '/vol/log/mysql /var/log/mysql none bind' "
|
||||
"| sudo tee -a /etc/fstab"
|
||||
"&& sudo mount /var/log/mysql")
|
||||
ssh.exec_command("sudo /etc/init.d/mysql start")
|
||||
|
||||
# NOTE(apavlov): add test DB
|
||||
ssh.exec_command("mysql -u root --password=rootpass -e "
|
||||
"'CREATE DATABASE tutorial_sample'")
|
||||
|
||||
resp = ssh.exec_command("mysql -u root --password=rootpass "
|
||||
"-e 'SHOW DATABASES'")
|
||||
self.assertIn("tutorial_sample", resp)
|
||||
|
||||
# NOTE(apavlov): make snapshot
|
||||
ssh.exec_command("mysql -u root --password=rootpass -e '"
|
||||
"FLUSH TABLES WITH READ LOCK;"
|
||||
"SHOW MASTER STATUS;"
|
||||
"SYSTEM sudo xfs_freeze -f /vol;'")
|
||||
|
||||
snapshot = self.ec2_client.create_snapshot(volume_id)
|
||||
self.addResourceCleanUp(self.destroy_snapshot_wait, snapshot)
|
||||
self.assertSnapshotStatusWait(snapshot, "completed")
|
||||
|
||||
ssh.exec_command("mysql -u root --password=rootpass -e '"
|
||||
"SYSTEM sudo xfs_freeze -u /vol;"
|
||||
"UNLOCK TABLES;'")
|
||||
|
||||
# NOTE(apavlov): cleanup
|
||||
ssh.exec_command("sudo /etc/init.d/mysql stop"
|
||||
"&& sudo umount /etc/mysql /var/lib/mysql /var/log/mysql /vol")
|
||||
|
||||
return snapshot
|
||||
|
||||
def _restore_mysql_db(self, ssh, volume_id):
|
||||
ssh.exec_command("sudo apt-get update")
|
||||
ssh.exec_command("sudo apt-get upgrade -y")
|
||||
|
||||
# install mysql
|
||||
ssh.exec_command("export DEBIAN_FRONTEND=noninteractive")
|
||||
ssh.exec_command("sudo -E apt-get install -y xfsprogs mysql-server")
|
||||
|
||||
ssh.exec_command("echo '/dev/" + self.volume_name
|
||||
+ " /vol xfs noatime 0 0' "
|
||||
"| sudo tee -a /etc/fstab")
|
||||
ssh.exec_command("sudo mkdir -m 000 /vol")
|
||||
ssh.exec_command("sudo mount /vol")
|
||||
|
||||
ssh.exec_command("sudo find /vol/{lib,log}/mysql/ ! -user root -print0"
|
||||
" | sudo xargs -0 -r chown mysql")
|
||||
ssh.exec_command("sudo find /vol/{lib,log}/mysql/ ! -group root -a !"
|
||||
" -group adm -print0 | sudo xargs -0 -r chgrp mysql")
|
||||
ssh.exec_command("sudo /etc/init.d/mysql stop")
|
||||
ssh.exec_command("echo '/vol/etc/mysql /etc/mysql none bind' "
|
||||
"| sudo tee -a /etc/fstab")
|
||||
ssh.exec_command("sudo mount /etc/mysql")
|
||||
ssh.exec_command("echo '/vol/lib/mysql /var/lib/mysql none bind' "
|
||||
"| sudo tee -a /etc/fstab")
|
||||
ssh.exec_command("sudo mount /var/lib/mysql")
|
||||
ssh.exec_command("echo '/vol/log/mysql /var/log/mysql none bind' "
|
||||
"| sudo tee -a /etc/fstab")
|
||||
ssh.exec_command("sudo mount /var/log/mysql")
|
||||
ssh.exec_command("sudo /etc/init.d/mysql start")
|
||||
|
||||
resp = ssh.exec_command("mysql -u root --password=rootpass "
|
||||
"-e 'SHOW DATABASES'")
|
||||
self.assertIn("tutorial_sample", resp)
|
||||
|
||||
# NOTE(apavlov): cleanup
|
||||
ssh.exec_command("sudo /etc/init.d/mysql stop"
|
||||
"&& sudo umount /etc/mysql /var/lib/mysql /var/log/mysql /vol")
|
||||
|
||||
return None
|
|
@ -1,110 +0,0 @@
|
|||
# Copyright 2014
|
||||
# The Cloudscaling Group, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from testtools import content as test_content
|
||||
|
||||
import tempest.cloudscaling.base as base
|
||||
import tempest.cloudscaling.thirdparty.scenario.aws_compat.base as aws_base
|
||||
from tempest.lib.common.utils.linux import remote_client
|
||||
from tempest.lib import decorators
|
||||
|
||||
import logging
|
||||
logging.getLogger('boto').setLevel(logging.CRITICAL)
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UnixBenchTest(base.BaseBenchmarkTest, aws_base.BaseAWSTest):
|
||||
"""UnixBench set of tests used to test performance compatibility to AWS"""
|
||||
|
||||
@classmethod
|
||||
@test.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(UnixBenchTest, cls).setUpClass()
|
||||
|
||||
cls._load_benchmark_data("UnixBenchTest")
|
||||
|
||||
cfg = cls.config.cloudscaling
|
||||
image_name = cfg.general_image_name
|
||||
cls.ssh_user = cfg.general_ssh_user_name
|
||||
|
||||
cls.image_id = cls._prepare_image_id(image_name)
|
||||
|
||||
cls.keypair = cls._prepare_key_pair()
|
||||
sg = cls._prepare_security_group()
|
||||
cls.sec_group_name = sg.name
|
||||
# NOTE(apavlov): ec2-run-instances --key KEYPAIR IMAGE
|
||||
reservation = cls.ec2_client.run_instances(cls.image_id,
|
||||
instance_type=cls.instance_type,
|
||||
key_name=cls.keypair.name,
|
||||
security_groups=(cls.sec_group_name,))
|
||||
cls.addResourceCleanUp(cls.destroy_reservation, reservation)
|
||||
cls.instance = reservation.instances[0]
|
||||
LOG.info("state: %s", cls.instance.state)
|
||||
# NOTE(apavlov): wait until it runs (ec2-describe-instances INSTANCE)
|
||||
cls._wait_instance_state(cls.instance, "running")
|
||||
cls._prepare_public_ip(cls.instance)
|
||||
|
||||
ip_address = cls._prepare_public_ip(cls.instance)
|
||||
cls.ssh = remote_client.RemoteClient(ip_address,
|
||||
cls.ssh_user,
|
||||
pkey=cls.keypair.material)
|
||||
|
||||
@decorators.attr(type='benchmark')
|
||||
def test_run_benchmark(self):
|
||||
"""Run UnixBench test on prepared instance"""
|
||||
if self.ssh is None:
|
||||
raise self.skipException("Booting failed")
|
||||
ssh = self.ssh
|
||||
|
||||
self._correct_ns_if_needed(ssh)
|
||||
|
||||
ssh.exec_command("sudo apt-get update && sudo apt-get upgrade -fy")
|
||||
ssh.exec_command("sudo apt-get update")
|
||||
ssh.exec_command("sudo apt-get install -y make gcc")
|
||||
ssh.exec_command("sudo apt-get install -y libx11-dev libgl1-mesa-dev "
|
||||
"libxext-dev perl perl-modules")
|
||||
ssh.exec_command("wget http://byte-unixbench.googlecode.com/files"
|
||||
"/UnixBench5.1.3.tgz")
|
||||
ssh.exec_command("tar xvf UnixBench5.1.3.tgz")
|
||||
resp = ssh.exec_command("cd UnixBench && ./Run")
|
||||
|
||||
i = resp.find("---------------")
|
||||
if i != -1:
|
||||
resp = resp[i:]
|
||||
resp = "zone: " + self.instance.placement + "\n" + resp
|
||||
|
||||
fail = None
|
||||
reference = self._get_benchmark_data()
|
||||
for k, v in reference.iteritems():
|
||||
i1 = resp.lower().find(k)
|
||||
if i1 == -1:
|
||||
continue
|
||||
|
||||
k = resp[i1:i1 + len(k)]
|
||||
i2 = resp.find("\n", i1)
|
||||
outp = resp[i1 + len(k):i2].split()[:2]
|
||||
if len(outp) < 2:
|
||||
continue
|
||||
|
||||
self.addDetail(k, test_content.text_content(
|
||||
outp[1] + "|" + outp[0] + "|Min: " + v[0] + "|Max: " + v[1]))
|
||||
|
||||
if fail is None and float(outp[0]) < float(v[0]):
|
||||
fail = (outp[0], outp[1], k, v[0])
|
||||
|
||||
if fail is not None:
|
||||
self.assertGreaterEqual(fail[0], fail[1],
|
||||
fail[2] + ": " +
|
||||
fail[0] + " " + fail[1] + " (current) < " +
|
||||
fail[3] + " " + fail[1] + " (AWS)")
|
|
@ -1,250 +0,0 @@
|
|||
# Copyright 2014
|
||||
# The Cloudscaling Group, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import time
|
||||
|
||||
from testtools import content as test_content
|
||||
|
||||
import tempest.cloudscaling.base as base
|
||||
import tempest.cloudscaling.thirdparty.scenario.aws_compat.base as aws_base
|
||||
import tempest.cloudscaling.utils as utils
|
||||
from tempest.lib.common.utils.linux import remote_client
|
||||
from tempest.lib import decorators
|
||||
from tempest.thirdparty.boto.utils import wait as boto_wait
|
||||
|
||||
import logging
|
||||
logging.getLogger('boto').setLevel(logging.CRITICAL)
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class VolumeBenchmarkTest(base.BaseBenchmarkTest, aws_base.BaseAWSTest):
|
||||
|
||||
class Context:
|
||||
instance = None
|
||||
ssh = None
|
||||
volume = None
|
||||
part_lines = None
|
||||
volume_ready = False
|
||||
volume_filled = False
|
||||
snapshot = None
|
||||
|
||||
@classmethod
|
||||
@test.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VolumeBenchmarkTest, cls).setUpClass()
|
||||
|
||||
cls._load_benchmark_data("VolumeBenchmarkTest")
|
||||
|
||||
cfg = cls.config.cloudscaling
|
||||
image_name = cfg.general_image_name
|
||||
cls.ssh_user = cfg.general_ssh_user_name
|
||||
cls.volume_size = cfg.volume_benchmark_volume_size_gb
|
||||
cls.volume_fill = cfg.volume_benchmark_volume_fill_percent
|
||||
cls.volume_attach_name = "sdh"
|
||||
cls.ctx = cls.Context()
|
||||
|
||||
cls.image_id = cls._prepare_image_id(image_name)
|
||||
|
||||
cls.keypair = cls._prepare_key_pair()
|
||||
sg = cls._prepare_security_group()
|
||||
cls.sec_group_name = sg.name
|
||||
|
||||
# NOTE(apavlov): ec2-run-instances --key KEYPAIR IMAGE
|
||||
reservation = cls.ec2_client.run_instances(cls.image_id,
|
||||
instance_type=cls.instance_type,
|
||||
key_name=cls.keypair.name,
|
||||
security_groups=(cls.sec_group_name,))
|
||||
cls.addResourceCleanUp(cls.destroy_reservation, reservation)
|
||||
instance = reservation.instances[0]
|
||||
LOG.info("state: %s", instance.state)
|
||||
# NOTE(apavlov): wait until it runs (ec2-describe-instances INSTANCE)
|
||||
cls._wait_instance_state(instance, "running")
|
||||
cls.ctx.instance = instance
|
||||
|
||||
ip_address = cls._prepare_public_ip(instance)
|
||||
ssh = remote_client.RemoteClient(ip_address,
|
||||
cls.ssh_user,
|
||||
pkey=cls.keypair.material)
|
||||
cls.ctx.ssh = ssh
|
||||
|
||||
def _volume_state(self):
|
||||
self.ctx.volume.update(validate=True)
|
||||
return self.ctx.volume.status
|
||||
|
||||
def _part_state(self):
|
||||
current = self.ctx.ssh.get_partitions().split('\n')
|
||||
if len(current) > len(self.ctx.part_lines):
|
||||
return 1
|
||||
if len(current) < len(self.ctx.part_lines):
|
||||
return -1
|
||||
return 0
|
||||
|
||||
def _start_test(self):
|
||||
self.start_time = time.time()
|
||||
|
||||
def _end_test(self, detail_description):
|
||||
end_time = time.time()
|
||||
self.test_time = end_time - self.start_time
|
||||
content = test_content.text_content(
|
||||
detail_description + " time: " + str(self.test_time) + "s")
|
||||
self.addDetail("Current", content)
|
||||
reference_time = self._get_benchmark_result()
|
||||
if reference_time is not None:
|
||||
content = test_content.text_content(
|
||||
"Min time: " + str(reference_time[0]) + "s, " +
|
||||
"Max time: " + str(reference_time[1]) + "s")
|
||||
self.addDetail("AWS", content)
|
||||
|
||||
def _check_test(self):
|
||||
reference_time = self._get_benchmark_result()
|
||||
if reference_time is not None:
|
||||
self.assertLessEqual(self.test_time, float(reference_time[1]),
|
||||
str(self.test_time) + "s (current) > " +
|
||||
reference_time[1] + "s (AWS)")
|
||||
|
||||
@decorators.attr(type='benchmark')
|
||||
def test_001_attach_volume(self):
|
||||
"""Attach volume"""
|
||||
|
||||
if self.ctx.ssh is None:
|
||||
raise self.skipException("Booting failed")
|
||||
|
||||
self._start_test()
|
||||
|
||||
# NOTE(apavlov): ec2-create-volume -z ZONE -s SIZE_GB
|
||||
zone = self.ctx.instance.placement
|
||||
volume = self.ec2_client.create_volume(self.volume_size, zone)
|
||||
self.addResourceCleanUp(self.destroy_volume_wait, volume)
|
||||
self.ctx.volume = volume
|
||||
# NOTE(apavlov): wait it (ec2-describe-volumes VOLUME)
|
||||
self.assertVolumeStatusWait(volume, "available")
|
||||
|
||||
# NOTE(apavlov): ec2-attach-volume -d /dev/XXX -i INSTANCE VOLUME
|
||||
# and wait until it will be available
|
||||
self.ctx.part_lines = self.ctx.ssh.get_partitions().split('\n')
|
||||
volume.attach(self.ctx.instance.id, "/dev/" + self.volume_attach_name)
|
||||
|
||||
# NOTE(apavlov): "attaching" invalid EC2 status #1074901
|
||||
self.assertVolumeStatusWait(self._volume_state, "in-use")
|
||||
boto_wait.re_search_wait(self._volume_state, "in-use")
|
||||
|
||||
boto_wait.state_wait(self._part_state, 1)
|
||||
part_lines_new = self.ctx.ssh.get_partitions().split('\n')
|
||||
volume_name = utils.detect_new_volume(self.ctx.part_lines,
|
||||
part_lines_new)
|
||||
self.ctx.part_lines = part_lines_new
|
||||
|
||||
self._end_test("Create and attach volume")
|
||||
|
||||
self.ctx.ssh.exec_command("PATH=$PATH:/usr/sbin:/usr/bin "
|
||||
"&& sudo mkfs.ext3 /dev/" + volume_name)
|
||||
self.ctx.ssh.exec_command("sudo mkdir -m 777 /vol "
|
||||
"&& sudo mount /dev/" + volume_name + " /vol")
|
||||
self.ctx.volume_ready = True
|
||||
|
||||
self._check_test()
|
||||
|
||||
@decorators.attr(type='benchmark')
|
||||
def test_002_fill_volume(self):
|
||||
"""Fill volume with data"""
|
||||
|
||||
if self.ctx.ssh is None:
|
||||
raise self.skipException("Booting failed")
|
||||
if not self.ctx.volume_ready:
|
||||
raise self.skipException("Volume preparation failed")
|
||||
|
||||
self._start_test()
|
||||
|
||||
self.ctx.ssh.exec_command("sudo mkdir -m 777 /vol/data")
|
||||
file_lines = 102 * int(self.volume_size)
|
||||
for i in xrange(int(self.volume_fill)):
|
||||
self.ctx.ssh.exec_command("cat /dev/urandom "
|
||||
"| tr -d -c 'a-zA-Z0-9' "
|
||||
"| fold -w 1020 "
|
||||
"| head -n " + str(file_lines) +
|
||||
" > /vol/data/file" + str(i))
|
||||
|
||||
self._end_test("Volume filling")
|
||||
|
||||
self.ctx.volume_filled = True
|
||||
|
||||
self._check_test()
|
||||
|
||||
@decorators.attr(type='benchmark')
|
||||
def test_003_snapshot_volume(self):
|
||||
"""Snapshot volume"""
|
||||
|
||||
if self.ctx.ssh is None:
|
||||
raise self.skipException("Booting failed")
|
||||
if not self.ctx.volume_filled:
|
||||
raise self.skipException("Volume filling failed")
|
||||
|
||||
self._start_test()
|
||||
|
||||
snapshot = self.ec2_client.create_snapshot(self.ctx.volume.id)
|
||||
self.addResourceCleanUp(self.destroy_snapshot_wait, snapshot)
|
||||
self.assertSnapshotStatusWait(snapshot, "completed")
|
||||
|
||||
self._end_test("Snapshot creation")
|
||||
|
||||
self.ctx.snapshot = snapshot
|
||||
|
||||
self._check_test()
|
||||
|
||||
@decorators.attr(type='benchmark')
|
||||
def test_004_clone_volume_snapshot(self):
|
||||
"""Clone volume"""
|
||||
|
||||
if self.ctx.ssh is None:
|
||||
raise self.skipException("Booting failed")
|
||||
if self.ctx.snapshot is None:
|
||||
raise self.skipException("Snapshot of volume failed")
|
||||
|
||||
self._start_test()
|
||||
|
||||
zone = self.ctx.instance.placement
|
||||
volume2 = self.ec2_client.create_volume(
|
||||
self.volume_size, zone, snapshot=self.ctx.snapshot)
|
||||
self.addResourceCleanUp(self.destroy_volume_wait, volume2)
|
||||
# NOTE(apavlov): wait it (ec2-describe-volumes VOLUME)
|
||||
self.assertVolumeStatusWait(volume2, "available")
|
||||
|
||||
self._end_test("Volume creation by snapshot")
|
||||
|
||||
self._check_test()
|
||||
|
||||
@decorators.attr(type='benchmark')
|
||||
def test_005_detach_volume(self):
|
||||
"""Detach volume"""
|
||||
|
||||
if self.ctx.ssh is None:
|
||||
raise self.skipException("Booting failed")
|
||||
if not self.ctx.volume_ready:
|
||||
raise self.skipException("Volume preparation failed")
|
||||
|
||||
self._start_test()
|
||||
|
||||
self.ctx.ssh.exec_command("sudo umount /vol")
|
||||
|
||||
self.ctx.volume.detach()
|
||||
|
||||
# NOTE(apavlov): "detaching" invalid EC2 status #1074901
|
||||
self.assertVolumeStatusWait(self._volume_state, "available")
|
||||
boto_wait.re_search_wait(self._volume_state, "available")
|
||||
|
||||
self._end_test("Detach volume")
|
||||
|
||||
boto_wait.state_wait(self._part_state, -1)
|
||||
|
||||
self._check_test()
|
|
@ -1,297 +0,0 @@
|
|||
# Copyright 2014
|
||||
# The Cloudscaling Group, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import threading
|
||||
|
||||
import boto.exception
|
||||
import netaddr
|
||||
|
||||
from tempest.cloudscaling import base
|
||||
import tempest.cloudscaling.thirdparty.scenario.aws_compat.base as aws_base
|
||||
from tempest.lib.common.utils.linux import remote_client
|
||||
from tempest import test
|
||||
from tempest.thirdparty.boto.utils import wait as boto_wait
|
||||
|
||||
import logging
|
||||
logging.getLogger('boto').setLevel(logging.CRITICAL)
|
||||
|
||||
|
||||
class VPC_Behavior_Base(aws_base.BaseVPCTest):
|
||||
"""Base class for AWS VPC behavior tests."""
|
||||
|
||||
@classmethod
|
||||
def _run_instance(cls, subnet, private_ip=None):
|
||||
params = {
|
||||
"key_name": cls.keypair.name,
|
||||
"instance_type": cls.instance_type,
|
||||
"placement": cls.zone,
|
||||
"subnet_id": subnet.id,
|
||||
}
|
||||
if private_ip:
|
||||
params["private_ip_address"] = str(private_ip)
|
||||
reservation = cls.vpc_client.run_instances(cls.image_id,
|
||||
**params)
|
||||
if reservation is None:
|
||||
raise base.TestCasePreparationError()
|
||||
cls.addResourceCleanUp(cls.destroy_reservation, reservation)
|
||||
if len(reservation.instances) != 1:
|
||||
raise base.TestCasePreparationError()
|
||||
instance = reservation.instances[0]
|
||||
return instance
|
||||
|
||||
|
||||
class VPC_Behavior(VPC_Behavior_Base):
|
||||
"""Test various behavior of VPC network."""
|
||||
|
||||
class TcpDumpRunner(object):
|
||||
timeout = None
|
||||
|
||||
def __init__(self, instance, ssh_user, ssh_keypair, parameters):
|
||||
ssh = remote_client.RemoteClient(instance.ip_address,
|
||||
ssh_user,
|
||||
pkey=ssh_keypair.material)
|
||||
ssh.ssh_client.channel_timeout = float(self.timeout)
|
||||
self.ssh = ssh
|
||||
self.parameters = parameters
|
||||
self.thread = None
|
||||
|
||||
def __enter__(self):
|
||||
self.ssh.exec_command("rm -f tcpdump.log")
|
||||
thread = threading.Thread(target=self._run_tcpdump)
|
||||
thread.start()
|
||||
self._sync()
|
||||
self.thread = thread
|
||||
return self
|
||||
|
||||
def __exit__(self, ex_type, ex_value, ex_traceback):
|
||||
self.stop()
|
||||
|
||||
def _run_tcpdump(self):
|
||||
self.ssh.exec_command("sudo tcpdump %s >tcpdump.log 2>&1" %
|
||||
self.parameters)
|
||||
|
||||
def _sync(self):
|
||||
def check_tcpdump_is_ready():
|
||||
resp = self.ssh.exec_command("test -f tcpdump.log && echo 1 "
|
||||
"|| echo 0")
|
||||
return int(resp) == 1
|
||||
boto_wait.state_wait(check_tcpdump_is_ready, True)
|
||||
|
||||
def stop(self):
|
||||
if self.thread is None:
|
||||
return
|
||||
self.ssh.exec_command("sudo pkill -SIGINT tcpdump")
|
||||
thread = self.thread
|
||||
self.thread = None
|
||||
thread.join(float(self.timeout))
|
||||
return not thread.is_alive()
|
||||
|
||||
def get_result(self):
|
||||
resp = self.ssh.exec_command("cat tcpdump.log")
|
||||
return resp
|
||||
|
||||
class Context(object):
|
||||
instance3 = None
|
||||
lease_file = None
|
||||
gateway = None
|
||||
|
||||
@classmethod
|
||||
@test.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VPC_Behavior, cls).setUpClass()
|
||||
cls.TcpDumpRunner.timeout = cls.config.boto.build_timeout
|
||||
cls.subnet = cls._prepare_vpc(cls.vpc_cidr, cls.subnet_cidr)
|
||||
cls.instance1 = cls._run_instance(cls.subnet)
|
||||
cls.instance2 = cls._run_instance(cls.subnet)
|
||||
cls._wait_instance_state(cls.instance1, "running")
|
||||
cls._wait_instance_state(cls.instance2, "running")
|
||||
cls.instance1.ip_address = cls._prepare_public_ip(cls.instance1)
|
||||
ssh = remote_client.RemoteClient(cls.instance1.ip_address,
|
||||
cls.ssh_user,
|
||||
pkey=cls.keypair.material)
|
||||
ssh.exec_command("sudo apt-get update")
|
||||
ssh.exec_command("sudo DEBIAN_FRONTEND=noninteractive apt-get -fqy "
|
||||
"install socat nmap")
|
||||
cls.ctx = cls.Context()
|
||||
|
||||
def test_011_check_network_gateway(self):
|
||||
"""Is gateway local to subnet?"""
|
||||
ssh = remote_client.RemoteClient(self.instance1.ip_address,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
resp = ssh.exec_command("route -n | awk '{ if ($1==\"0.0.0.0\" && "
|
||||
"$4 ~ /.*G.*/) print $2 }'")
|
||||
lines = resp.splitlines()
|
||||
self.assertEqual(1, len(lines))
|
||||
gateway = netaddr.IPAddress(lines[0])
|
||||
self.ctx.gateway = gateway
|
||||
self.assertTrue(gateway in self.subnet_cidr)
|
||||
|
||||
def test_012_check_dhcp_grant_ip(self):
|
||||
"""Whether dhcp provide IP address?"""
|
||||
instance = self._run_instance(self.subnet)
|
||||
state = self.waitInstanceState(instance, "running")
|
||||
if state != "running":
|
||||
raise base.TestCasePreparationError()
|
||||
self.assertTrue(instance.private_ip_address)
|
||||
instance.ip_address = self._prepare_public_ip(instance)
|
||||
self.ctx.instance3 = instance
|
||||
|
||||
def test_013_check_dhcp_lease(self):
|
||||
"""Whether IP address was obtained by dhcp?"""
|
||||
if self.ctx.instance3 is None:
|
||||
self.skipTest("Instance 3 was not initialized")
|
||||
ssh = remote_client.RemoteClient(self.ctx.instance3.ip_address,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
resp = ssh.exec_command("ps -eo comm,args | grep -m 1 dhclient")
|
||||
args = resp.split()
|
||||
if len(args) <= 2 or not args[0].startswith('dhclient'):
|
||||
raise base.TestCasePreparationError()
|
||||
is_lf = False
|
||||
lease_file = "/var/lib/dhcp/dhclient.leases"
|
||||
for arg in args:
|
||||
if is_lf:
|
||||
lease_file = arg
|
||||
is_lf = False
|
||||
elif arg == "-lf":
|
||||
is_lf = True
|
||||
resp = ssh.exec_command("test -f %s && echo 1 || echo 0" % lease_file)
|
||||
self.assertEqual(1, int(resp))
|
||||
self.ctx.lease_file = lease_file
|
||||
resp = ssh.exec_command("grep 'fixed-address ' %s | tail -n 1 | "
|
||||
"awk '{ print $2 }' | sed -e 's/;//'" %
|
||||
lease_file)
|
||||
lines = resp.splitlines()
|
||||
self.assertEqual(1, len(lines))
|
||||
self.assertEqual(self.ctx.instance3.private_ip_address, lines[0])
|
||||
date = ssh.exec_command("date -u +%Y/%m/%d%H:%M:%S")
|
||||
self.assertTrue(date)
|
||||
resp = ssh.exec_command("grep 'renew ' %s | tail -n 1 | "
|
||||
"awk '{ print $3$4 }' | sed -e 's/;//'" %
|
||||
lease_file)
|
||||
self.assertLess(date, resp)
|
||||
|
||||
def test_014_check_dhcp_sends_mtu_size(self):
|
||||
"""Check DHCP sends MTU size."""
|
||||
if self.ctx.lease_file is None:
|
||||
self.skipTest("Dhcp lease file was not found")
|
||||
ssh = remote_client.RemoteClient(self.ctx.instance3.ip_address,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
resp = ssh.exec_command("grep 'option interface-mtu ' %s" %
|
||||
self.ctx.lease_file)
|
||||
self.assertLess(0, len(resp.splitlines()))
|
||||
|
||||
def test_015_check_dhcp_distribute_host_name_size(self):
|
||||
"""Check DHCP distributes host hame."""
|
||||
if self.ctx.lease_file is None:
|
||||
self.skipTest("Dhcp lease file was not found")
|
||||
ssh = remote_client.RemoteClient(self.ctx.instance3.ip_address,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
resp = ssh.exec_command("grep 'option host-name ' %s" %
|
||||
self.ctx.lease_file)
|
||||
self.assertLess(0, len(resp.splitlines()))
|
||||
|
||||
def test_021_check_traffic_visibility(self):
|
||||
"""Are other VMs visible?"""
|
||||
if self.ctx.instance3 is None:
|
||||
self.skipTest("Instance 3 was not initialized")
|
||||
with self.TcpDumpRunner(self.ctx.instance3,
|
||||
self.ssh_user,
|
||||
self.keypair,
|
||||
"ip proto \\\\icmp") as tdump:
|
||||
ssh = remote_client.RemoteClient(self.instance1.ip_address,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
ssh.exec_command("ping -c 1 %s" %
|
||||
self.instance2.private_ip_address)
|
||||
if not tdump.stop():
|
||||
raise base.TestCasePreparationError()
|
||||
resp = tdump.get_result()
|
||||
for line in resp.splitlines():
|
||||
if line.endswith("packets captured"):
|
||||
captured = line
|
||||
break
|
||||
tokens = captured.split()
|
||||
packets = int(tokens[0])
|
||||
self.assertEqual(0, packets)
|
||||
|
||||
def test_022_check_broadcast_visible(self):
|
||||
"""Is broadcast traffic visible?"""
|
||||
if self.ctx.instance3 is None:
|
||||
self.skipTest("Instance 3 was not initialized")
|
||||
with self.TcpDumpRunner(self.ctx.instance3,
|
||||
self.ssh_user,
|
||||
self.keypair,
|
||||
"ip broadcast") as tdump:
|
||||
ssh = remote_client.RemoteClient(self.instance1.ip_address,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
ssh.exec_command("echo ping |"
|
||||
"socat - UDP4-DATAGRAM:255.255.255.255:6666,"
|
||||
"broadcast")
|
||||
if not tdump.stop():
|
||||
raise base.TestCasePreparationError()
|
||||
resp = tdump.get_result()
|
||||
captured = ""
|
||||
for line in resp.splitlines():
|
||||
if line.endswith(" captured"):
|
||||
captured = line
|
||||
break
|
||||
tokens = captured.split()
|
||||
packets = int(tokens[0])
|
||||
self.assertEqual(0, packets)
|
||||
|
||||
def test_023_check_multicast_visible(self):
|
||||
"""Is multicast traffic visible?"""
|
||||
if self.ctx.instance3 is None:
|
||||
self.skipTest("Instance 3 was not initialized")
|
||||
with self.TcpDumpRunner(self.ctx.instance3,
|
||||
self.ssh_user,
|
||||
self.keypair,
|
||||
"ip multicast") as tdump:
|
||||
ssh = remote_client.RemoteClient(self.instance1.ip_address,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
ssh.exec_command("echo ping |"
|
||||
"socat - UDP4-DATAGRAM:239.1.1.1:6666")
|
||||
if not tdump.stop():
|
||||
raise base.TestCasePreparationError()
|
||||
resp = tdump.get_result()
|
||||
captured = ""
|
||||
for line in resp.splitlines():
|
||||
if line.endswith(" captured"):
|
||||
captured = line
|
||||
break
|
||||
tokens = captured.split()
|
||||
packets = int(tokens[0])
|
||||
self.assertEqual(0, packets)
|
||||
|
||||
def test_031_scan_gateway_ports(self):
|
||||
"""Are gateway ports closed?"""
|
||||
if self.ctx.gateway is None:
|
||||
self.skipTest("Subnet's gateway was not found")
|
||||
ssh = remote_client.RemoteClient(self.instance1.ip_address,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
ssh.ssh_client.channel_timeout = 600
|
||||
resp = ssh.exec_command("sudo nmap -PN %s" % str(self.ctx.gateway))
|
||||
all_closed_msg = ("All 1000 scanned ports on %s are " %
|
||||
str(self.ctx.gateway))
|
||||
for line in resp.splitlines():
|
||||
if line.startswith(all_closed_msg):
|
||||
return
|
||||
self.fail("Some gateway ports are open")
|
|
@ -1,188 +0,0 @@
|
|||
# Copyright 2014
|
||||
# The Cloudscaling Group, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import select
|
||||
|
||||
from testtools import content as test_content
|
||||
|
||||
from tempest.cloudscaling import base
|
||||
import tempest.cloudscaling.thirdparty.scenario.aws_compat.base as aws_base
|
||||
from tempest import exceptions
|
||||
from tempest.lib.common.utils.linux import remote_client
|
||||
from tempest.lib import decorators
|
||||
|
||||
import logging
|
||||
logging.getLogger('boto').setLevel(logging.CRITICAL)
|
||||
|
||||
|
||||
class IPerfServer(object):
|
||||
"""Wrapper to use iperf server in tests."""
|
||||
cmd = "iperf -s"
|
||||
|
||||
def __init__(self, instance, ssh_user, ssh_keypair):
|
||||
self.instance = instance
|
||||
self.ssh_user = ssh_user
|
||||
self.ssh_keypair = ssh_keypair
|
||||
|
||||
def __enter__(self):
|
||||
# NOTE(ft): Iperf doesn't close stdout in server mode
|
||||
# but standard exec_command waits for it
|
||||
# so instead of use it we waits for some string in output
|
||||
ssh = remote_client.RemoteClient(self.instance.ip_address,
|
||||
self.ssh_user,
|
||||
pkey=self.ssh_keypair.material)
|
||||
ssh_conn = ssh.ssh_client._get_ssh_connection()
|
||||
chan = ssh_conn.get_transport().open_session()
|
||||
chan.get_pty() # NOTE(ft): to stop iperf with session end
|
||||
chan.fileno()
|
||||
chan.exec_command(self.cmd)
|
||||
|
||||
started = False
|
||||
out_data = []
|
||||
err_data = []
|
||||
select_params = [chan], [], [], ssh.ssh_client.channel_timeout
|
||||
while True:
|
||||
ready = select.select(*select_params)
|
||||
if not any(ready):
|
||||
raise exceptions.TimeoutException(
|
||||
"Cannot start iperf server on host '{1}'.".format(
|
||||
self.host))
|
||||
if not ready[0]:
|
||||
continue
|
||||
out_chunk = err_chunk = None
|
||||
if chan.recv_ready():
|
||||
out_chunk = chan.recv(ssh.ssh_client.buf_size)
|
||||
out_data += out_chunk,
|
||||
if chan.recv_stderr_ready():
|
||||
err_chunk = chan.recv_stderr(ssh.ssh_client.buf_size)
|
||||
err_data += err_chunk,
|
||||
if chan.exit_status_ready():
|
||||
exit_status = chan.recv_exit_status()
|
||||
if 0 != exit_status or len(err_data) > 0:
|
||||
raise exceptions.SSHExecCommandFailed(
|
||||
command=self.cmd, exit_status=exit_status,
|
||||
strerror=''.join(err_data))
|
||||
lines = ''.join(out_data).splitlines()
|
||||
for line in lines:
|
||||
if line.startswith("Server listening"):
|
||||
started = True
|
||||
break
|
||||
if (started or
|
||||
chan.closed and not err_chunk and not out_chunk):
|
||||
break
|
||||
self.ssh = ssh
|
||||
self.ssh_conn = ssh_conn
|
||||
self.chan = chan
|
||||
|
||||
def __exit__(self, ex_type, ex_value, ex_traceback):
|
||||
self.chan.close()
|
||||
self.ssh_conn.close()
|
||||
|
||||
|
||||
class VPC_Benchmark(aws_base.BaseVPCTest, base.BaseBenchmarkTest):
|
||||
"""Benchmark VPC network throughput."""
|
||||
|
||||
@classmethod
|
||||
@test.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VPC_Benchmark, cls).setUpClass()
|
||||
cls.keypair = cls._prepare_key_pair()
|
||||
subnet = cls._prepare_vpc(cls.vpc_cidr, cls.subnet_cidr)
|
||||
|
||||
reservation = cls.vpc_client.run_instances(
|
||||
cls.image_id,
|
||||
min_count=2, max_count=2,
|
||||
key_name=cls.keypair.name,
|
||||
instance_type=cls.instance_type,
|
||||
placement=cls.zone,
|
||||
subnet_id=subnet.id)
|
||||
if reservation is None:
|
||||
raise base.TestCasePreparationError()
|
||||
cls.addResourceCleanUp(cls.destroy_reservation, reservation)
|
||||
if len(reservation.instances) != 2:
|
||||
raise base.TestCasePreparationError()
|
||||
cls.instance1 = reservation.instances[0]
|
||||
cls.instance2 = reservation.instances[1]
|
||||
cls._wait_instance_state(cls.instance1, "running")
|
||||
cls._wait_instance_state(cls.instance2, "running")
|
||||
cls._prepare_public_ip(cls.instance1)
|
||||
cls._prepare_public_ip(cls.instance2)
|
||||
|
||||
def install_iperf(instance):
|
||||
try:
|
||||
ssh = remote_client.RemoteClient(instance.ip_address,
|
||||
cls.ssh_user,
|
||||
pkey=cls.keypair.material)
|
||||
except exceptions.SSHTimeout:
|
||||
raise base.TestCasePreparationError()
|
||||
ssh.exec_command("sudo apt-get update && sudo apt-get upgrade -y")
|
||||
ssh.exec_command("sudo apt-get update")
|
||||
ssh.exec_command("sudo apt-get install iperf")
|
||||
install_iperf(cls.instance1)
|
||||
install_iperf(cls.instance2)
|
||||
|
||||
cfg = cls.config.cloudscaling
|
||||
cls.network_performance_class = cfg.network_performance_class
|
||||
cls._load_benchmark_data("AWS_VPC_Benchmark")
|
||||
|
||||
def _get_rate(self, resp):
|
||||
resp_items = resp.split(",")
|
||||
rate = resp_items[len(resp_items) - 1]
|
||||
return int(rate) / 1000000
|
||||
|
||||
def _check_test(self, rate):
|
||||
if not self.network_performance_class:
|
||||
return
|
||||
reference = self._get_benchmark_result(self.network_performance_class)
|
||||
if reference is not None:
|
||||
content = test_content.text_content(
|
||||
"Min rate: %sMbits/sec, Max rate: %sMBits/sec" %
|
||||
(reference[0], reference[1]))
|
||||
self.addDetail("AWS", content)
|
||||
self.assertGreaterEqual(rate, float(reference[0]),
|
||||
"%sMbits/sec (current) < %sMbits/sec (AWS)" %
|
||||
(rate, reference[0]))
|
||||
|
||||
@decorators.attr(type='benchmark')
|
||||
def test_001_internal_vpc_tcp_150MB_throughput(self):
|
||||
"""Measure internal VPC network throughput for 150 MBytes transmit."""
|
||||
if self.keypair is None:
|
||||
self.skipTest("Environment was not initialized")
|
||||
with IPerfServer(self.instance1, self.ssh_user, self.keypair):
|
||||
ssh = remote_client.RemoteClient(self.instance2.ip_address,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
resp = ssh.exec_command("iperf -c %s -n 150M -x CMSV -y C" %
|
||||
self.instance1.private_ip_address)
|
||||
rate = self._get_rate(resp)
|
||||
self.addDetail("Current", test_content.text_content(
|
||||
"150 MBytes throughput: %s Mbits/sec" % rate))
|
||||
self._check_test(rate)
|
||||
|
||||
@decorators.attr(type='benchmark')
|
||||
def test_002_internal_vpc_tcp_2mins_throughput(self):
|
||||
"""Measure internal VPC network throughput for 2 mins transmit."""
|
||||
if self.keypair is None:
|
||||
self.skipTest("Environment was not initialized")
|
||||
with IPerfServer(self.instance1, self.ssh_user, self.keypair):
|
||||
ssh = remote_client.RemoteClient(self.instance2.ip_address,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
ssh.ssh_client.channel_timeout = 130
|
||||
resp = ssh.exec_command("iperf -c %s -t 120 -x CMSV -y C" %
|
||||
self.instance1.private_ip_address)
|
||||
rate = self._get_rate(resp)
|
||||
self.addDetail("Current", test_content.text_content(
|
||||
"2 mins throughput: %s Mbits/sec" % rate))
|
||||
self._check_test(rate)
|
|
@ -1,451 +0,0 @@
|
|||
# Copyright 2014
|
||||
# The Cloudscaling Group, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from boto.ec2 import networkinterface
|
||||
import netaddr
|
||||
|
||||
import tempest.cloudscaling.thirdparty.scenario.aws_compat.base as aws_base
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib.common.utils.linux import remote_client
|
||||
from tempest import test
|
||||
|
||||
import logging
|
||||
logging.getLogger('boto').setLevel(logging.CRITICAL)
|
||||
|
||||
|
||||
class VPC_NAT_Scenario(aws_base.BaseAWSTest):
|
||||
"""
|
||||
Based on 'VPC with Public and Private Subnets' scenario
|
||||
(http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Scenario2.html)
|
||||
Adapted to work with OpenStack with the following differences:
|
||||
1. DNS is set up via DHCP options to 8.8.8.8 (boto has a bug, see Note).
|
||||
2. Opened DNS ports (53) in DB and NAT security groups.
|
||||
3. NAT instance is created with 2 interfaces in different subnets.
|
||||
4. SourceDestCheck is disabled for second interface of NAT instance.
|
||||
5. Default route in main route table is set to point to this interface.
|
||||
As a result, DB instance's default route goes through the second interface
|
||||
of NAT instance which is in the same subnet as the DB instance.
|
||||
To allow several private subnets to work through the same NAT, more
|
||||
secondary interfaces should be added to NAT instance for all of that
|
||||
subnets, and separate route tables should be created for each of the
|
||||
subnets.
|
||||
"""
|
||||
# NOTE(Alex) At the moment of this test's creation, boto has a bug with
|
||||
# parsing result of setting up DHCP options. Order of the Key-Values
|
||||
# returned in OpenStack for the Dictionaries is different from AWS's.
|
||||
# Potential fix should be done in boto/vpc/dhcpoptions.py:
|
||||
# DhcpConfigSet can be changed to:
|
||||
#
|
||||
# class DhcpConfigSet(dict):
|
||||
#
|
||||
# def startElement(self, name, attrs, connection):
|
||||
# if name == 'valueSet':
|
||||
# if not hasattr(self, '_value'):
|
||||
# self._value = DhcpValueSet()
|
||||
# return self._value
|
||||
#
|
||||
# def endElement(self, name, value, connection):
|
||||
# if name == 'valueSet':
|
||||
# if hasattr(self, '_name'):
|
||||
# self[self._name] = self._value
|
||||
# if name == 'key':
|
||||
# self._name = value
|
||||
# if hasattr(self, '_value'):
|
||||
# self[self._name] = self._value
|
||||
|
||||
class Context(object):
|
||||
vpc = None
|
||||
internet_gateway = None
|
||||
web_subnet = None
|
||||
db_subnet = None
|
||||
main_route_table = None
|
||||
custom_route_table = None
|
||||
web_security_group = None
|
||||
nat_security_group = None
|
||||
db_security_group = None
|
||||
web_instance = None
|
||||
db_instance = None
|
||||
nat_instance = None
|
||||
|
||||
@classmethod
|
||||
@test.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VPC_NAT_Scenario, cls).setUpClass()
|
||||
cls.ctx = cls.Context()
|
||||
cls.zone = cls.config.boto.aws_zone
|
||||
cfg = cls.config.cloudscaling
|
||||
cls.ssh_user = cfg.general_ssh_user_name
|
||||
cls.vpc_cidr = netaddr.IPNetwork(cfg.vpc_cidr)
|
||||
cls.web_subnet, cls.db_subnet = cls.vpc_cidr.subnet(
|
||||
cfg.vpc_subnet_prefix, 2)
|
||||
cls.test_client_cidr = netaddr.IPNetwork(cfg.test_client_cidr)
|
||||
cls.image_id = cls._prepare_image_id(cfg.general_image_name)
|
||||
cls.keypair = cls._prepare_key_pair()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
if cls.ctx is not None:
|
||||
for group in [cls.ctx.web_security_group,
|
||||
cls.ctx.nat_security_group,
|
||||
cls.ctx.db_security_group]:
|
||||
if not group:
|
||||
continue
|
||||
try:
|
||||
cls._revoke_security_group_linked_rules(group)
|
||||
except Exception:
|
||||
pass
|
||||
super(VPC_NAT_Scenario, cls).tearDownClass()
|
||||
|
||||
@classmethod
|
||||
def _revoke_security_group_linked_rules(cls, group):
|
||||
groups = cls.vpc_client.get_all_security_groups(group_ids=[group.id])
|
||||
if len(groups) == 0:
|
||||
return
|
||||
sg = groups[0]
|
||||
for rule in sg.rules:
|
||||
for grant in rule.grants:
|
||||
if not grant.cidr_ip:
|
||||
cls.vpc_client.revoke_security_group(
|
||||
group_id=sg.id,
|
||||
ip_protocol=rule.ip_protocol,
|
||||
from_port=rule.from_port,
|
||||
to_port=rule.to_port,
|
||||
src_security_group_group_id=grant.groupId)
|
||||
for rule in sg.rules_egress:
|
||||
for grant in rule.grants:
|
||||
if not grant.cidr_ip:
|
||||
cls.vpc_client.revoke_security_group_egress(
|
||||
sg.id,
|
||||
rule.ip_protocol,
|
||||
from_port=rule.from_port,
|
||||
to_port=rule.to_port,
|
||||
src_group_id=grant.groupId)
|
||||
|
||||
def test_000_create_vpc(self):
|
||||
"""Create VPC"""
|
||||
dhcp_opts = self.vpc_client.create_dhcp_options(
|
||||
domain_name_servers=['8.8.8.8'])
|
||||
self.assertIsNotNone(dhcp_opts)
|
||||
self.assertTrue(dhcp_opts.id)
|
||||
self.addResourceCleanUp(self.vpc_client.delete_dhcp_options,
|
||||
dhcp_opts.id)
|
||||
vpc = self.vpc_client.create_vpc(str(self.vpc_cidr))
|
||||
self.assertIsNotNone(vpc)
|
||||
self.assertTrue(vpc.id)
|
||||
self.addResourceCleanUp(self.vpc_client.delete_vpc, vpc.id)
|
||||
self.assertTrue(self.vpc_client.associate_dhcp_options(dhcp_opts.id,
|
||||
vpc.id))
|
||||
self.ctx.vpc = vpc
|
||||
|
||||
def test_001_create_internet_gateway(self):
|
||||
"""Create internet gateway"""
|
||||
ig = self.vpc_client.create_internet_gateway()
|
||||
self.assertIsNotNone(ig)
|
||||
self.assertTrue(ig.id)
|
||||
self.addResourceCleanUp(self._destroy_internet_gateway, ig)
|
||||
status = self.vpc_client.attach_internet_gateway(ig.id,
|
||||
self.ctx.vpc.id)
|
||||
self.assertTrue(status)
|
||||
self.ctx.internet_gateway = ig
|
||||
|
||||
def test_010_create_subnets(self):
|
||||
"""Create subnets"""
|
||||
sn = self.vpc_client.create_subnet(self.ctx.vpc.id,
|
||||
str(self.web_subnet),
|
||||
self.zone)
|
||||
self.assertIsNotNone(sn)
|
||||
self.assertTrue(sn.id)
|
||||
self.addResourceCleanUp(self.vpc_client.delete_subnet, sn.id)
|
||||
self.ctx.web_subnet = sn
|
||||
sn = self.vpc_client.create_subnet(self.ctx.vpc.id,
|
||||
str(self.db_subnet),
|
||||
self.zone)
|
||||
self.assertIsNotNone(sn)
|
||||
self.assertTrue(sn.id)
|
||||
self.addResourceCleanUp(self.vpc_client.delete_subnet, sn.id)
|
||||
self.ctx.db_subnet = sn
|
||||
|
||||
def test_020_get_main_route_table(self):
|
||||
"""Describe auto created route table"""
|
||||
rtables = self.vpc_client.get_all_route_tables(
|
||||
filters=[("vpc-id", self.ctx.vpc.id)])
|
||||
self.assertIsNotNone(rtables)
|
||||
self.assertEqual(1, len(rtables))
|
||||
self.ctx.main_route_table = rtables[0]
|
||||
|
||||
def test_025_create_custom_route_table(self):
|
||||
"""Create route table for web servers"""
|
||||
rtable = self.vpc_client.create_route_table(self.ctx.vpc.id)
|
||||
self.assertIsNotNone(rtable)
|
||||
self.assertTrue(rtable.id)
|
||||
self.addResourceCleanUp(self.vpc_client.delete_route_table, rtable.id)
|
||||
ig = self.ctx.internet_gateway
|
||||
status = self.vpc_client.create_route(rtable.id, "0.0.0.0/0",
|
||||
gateway_id=ig.id)
|
||||
self.assertTrue(status)
|
||||
association_id = self.vpc_client.associate_route_table(
|
||||
rtable.id, self.ctx.web_subnet.id)
|
||||
self.assertTrue(association_id)
|
||||
self.addResourceCleanUp(self.vpc_client.disassociate_route_table,
|
||||
association_id)
|
||||
self.ctx.custom_route_table = rtable
|
||||
|
||||
def test_050_create_security_groups(self):
|
||||
"""Create and tune security groups"""
|
||||
sg = self.vpc_client.create_security_group(
|
||||
data_utils.rand_name("WebServerSG-"),
|
||||
data_utils.rand_name("description "),
|
||||
self.ctx.vpc.id)
|
||||
self.assertIsNotNone(sg)
|
||||
self.assertTrue(sg.id)
|
||||
self.addResourceCleanUp(self._destroy_security_group_wait, sg)
|
||||
self.ctx.web_security_group = sg
|
||||
sg = self.vpc_client.create_security_group(
|
||||
data_utils.rand_name("NATSG-"),
|
||||
data_utils.rand_name("description "),
|
||||
self.ctx.vpc.id)
|
||||
self.assertIsNotNone(sg)
|
||||
self.assertTrue(sg.id)
|
||||
self.addResourceCleanUp(self._destroy_security_group_wait, sg)
|
||||
self.ctx.nat_security_group = sg
|
||||
sg = self.vpc_client.create_security_group(
|
||||
data_utils.rand_name("DBServerSG-"),
|
||||
data_utils.rand_name("description "),
|
||||
self.ctx.vpc.id)
|
||||
self.assertIsNotNone(sg)
|
||||
self.assertTrue(sg.id)
|
||||
self.addResourceCleanUp(self._destroy_security_group_wait, sg)
|
||||
self.ctx.db_security_group = sg
|
||||
|
||||
sg = self.ctx.web_security_group
|
||||
status = self.vpc_client.revoke_security_group_egress(
|
||||
sg.id, "-1", cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 1433, 1433,
|
||||
src_group_id=self.ctx.db_security_group.id)
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 3306, 3306,
|
||||
src_group_id=self.ctx.db_security_group.id)
|
||||
self.assertTrue(status)
|
||||
# NOTE(ft): especially for connectivity test
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 80, 80, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
# NOTE(ft): especially for connectivity test
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 22, 22,
|
||||
src_group_id=self.ctx.db_security_group.id)
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=80, to_port=80,
|
||||
cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=443, to_port=443,
|
||||
cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=22, to_port=22,
|
||||
cidr_ip=str(self.test_client_cidr))
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=3389,
|
||||
to_port=3389, cidr_ip=str(self.test_client_cidr))
|
||||
self.assertTrue(status)
|
||||
|
||||
sg = self.ctx.nat_security_group
|
||||
status = self.vpc_client.revoke_security_group_egress(
|
||||
sg.id, "-1", cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 80, 80, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 443, 443, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 53, 53, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "udp", 53, 53, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=53,
|
||||
to_port=53, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="udp", from_port=53,
|
||||
to_port=53, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=80, to_port=80,
|
||||
cidr_ip=str(self.db_subnet))
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=443, to_port=443,
|
||||
cidr_ip=str(self.db_subnet))
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=22, to_port=22,
|
||||
cidr_ip=str(self.test_client_cidr))
|
||||
self.assertTrue(status)
|
||||
|
||||
sg = self.ctx.db_security_group
|
||||
status = self.vpc_client.revoke_security_group_egress(
|
||||
sg.id, "-1", cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 80, 80, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 443, 443, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 53, 53, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "udp", 53, 53, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp",
|
||||
from_port=1433,
|
||||
to_port=1433,
|
||||
src_security_group_group_id=self.ctx.web_security_group.id)
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp",
|
||||
from_port=3306,
|
||||
to_port=3306,
|
||||
src_security_group_group_id=self.ctx.web_security_group.id)
|
||||
self.assertTrue(status)
|
||||
# NOTE(ft): especially for connectivity test
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp",
|
||||
from_port=22,
|
||||
to_port=22,
|
||||
src_security_group_group_id=self.ctx.web_security_group.id)
|
||||
self.assertTrue(status)
|
||||
|
||||
def test_100_launch_nat_instance(self):
|
||||
"""Launch instances for NAT server"""
|
||||
interface_web = networkinterface.NetworkInterfaceSpecification(
|
||||
subnet_id=self.ctx.web_subnet.id,
|
||||
groups=[self.ctx.nat_security_group.id])
|
||||
interface_db = networkinterface.NetworkInterfaceSpecification(
|
||||
subnet_id=self.ctx.db_subnet.id,
|
||||
groups=[self.ctx.nat_security_group.id])
|
||||
reservation = self.vpc_client.run_instances(
|
||||
self.image_id,
|
||||
key_name=self.keypair.name,
|
||||
# security_group_ids=[self.ctx.nat_security_group.id],
|
||||
instance_type=self.instance_type,
|
||||
placement=self.zone,
|
||||
# subnet_id=self.ctx.web_subnet.id
|
||||
network_interfaces=(
|
||||
networkinterface.NetworkInterfaceCollection(
|
||||
interface_web, interface_db))
|
||||
)
|
||||
self.assertIsNotNone(reservation)
|
||||
self.addResourceCleanUp(self.destroy_reservation, reservation)
|
||||
self.assertEqual(1, len(reservation.instances))
|
||||
instance = reservation.instances[0]
|
||||
if instance.state != "running":
|
||||
self.assertInstanceStateWait(instance, "running")
|
||||
instance.ip_address = self._prepare_public_ip(
|
||||
instance,
|
||||
instance.interfaces[0].id)
|
||||
internal_interface_id = instance.interfaces[1].id
|
||||
status = self.vpc_client.modify_network_interface_attribute(
|
||||
internal_interface_id,
|
||||
attr='sourceDestCheck',
|
||||
value=False)
|
||||
self.assertTrue(status)
|
||||
|
||||
rtable = self.ctx.main_route_table
|
||||
status = self.vpc_client.create_route(
|
||||
rtable.id, "0.0.0.0/0",
|
||||
interface_id=internal_interface_id)
|
||||
self.assertTrue(status)
|
||||
self.ctx.nat_instance = instance
|
||||
|
||||
def test_101_launch_instances(self):
|
||||
"""Launch instances for web server and db server"""
|
||||
reservation = self.vpc_client.run_instances(
|
||||
self.image_id,
|
||||
key_name=self.keypair.name,
|
||||
security_group_ids=[self.ctx.web_security_group.id],
|
||||
instance_type=self.instance_type,
|
||||
placement=self.zone,
|
||||
subnet_id=self.ctx.web_subnet.id)
|
||||
self.assertIsNotNone(reservation)
|
||||
self.addResourceCleanUp(self.destroy_reservation, reservation)
|
||||
self.assertEqual(1, len(reservation.instances))
|
||||
instance = reservation.instances[0]
|
||||
if instance.state != "running":
|
||||
self.assertInstanceStateWait(instance, "running")
|
||||
instance.ip_address = self._prepare_public_ip(instance)
|
||||
self.ctx.web_instance = instance
|
||||
|
||||
reservation = self.vpc_client.run_instances(
|
||||
self.image_id,
|
||||
key_name=self.keypair.name,
|
||||
security_group_ids=[self.ctx.db_security_group.id],
|
||||
instance_type=self.instance_type,
|
||||
placement=self.zone,
|
||||
subnet_id=self.ctx.db_subnet.id)
|
||||
self.assertIsNotNone(reservation)
|
||||
self.addResourceCleanUp(self.destroy_reservation, reservation)
|
||||
self.assertEqual(1, len(reservation.instances))
|
||||
instance = reservation.instances[0]
|
||||
if instance.state != "running":
|
||||
self.assertInstanceStateWait(instance, "running")
|
||||
self.ctx.db_instance = instance
|
||||
|
||||
def test_102_tune_nat_instance(self):
|
||||
"""Tune NAT in NAT instance"""
|
||||
instance = self.ctx.nat_instance
|
||||
address = instance.ip_address
|
||||
ssh = remote_client.RemoteClient(address,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
|
||||
ssh.exec_command("sudo iptables -t nat -A POSTROUTING -s %s "
|
||||
"-o eth0 -j MASQUERADE" % str(self.vpc_cidr))
|
||||
ssh.exec_command("sudo sysctl -w net.ipv4.ip_forward=1")
|
||||
ssh.exec_command("echo $'auto eth1\niface eth1 inet dhcp\n' "
|
||||
"| sudo tee -a /etc/network/interfaces.d/eth1.cfg")
|
||||
ssh.exec_command("sudo ifup eth1")
|
||||
|
||||
def test_200_check_connectivity(self):
|
||||
"""Check inside and outside connectivities"""
|
||||
web_ip = self.ctx.web_instance.ip_address
|
||||
db_ip = self.ctx.db_instance.private_ip_address
|
||||
ssh = remote_client.RemoteClient(web_ip,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
ssh_conn = ssh.ssh_client._get_ssh_connection()
|
||||
sftp = ssh_conn.open_sftp()
|
||||
fr = sftp.file("key.pem", 'wb')
|
||||
fr.set_pipelined(True)
|
||||
fr.write(self.keypair.material)
|
||||
fr.close()
|
||||
ssh_conn.close()
|
||||
ssh.exec_command('chmod 400 key.pem')
|
||||
ssh.exec_command(
|
||||
"ssh -i key.pem -o UserKnownHostsFile=/dev/null "
|
||||
"-o StrictHostKeyChecking=no %(user)s@%(ip)s "
|
||||
"curl -s http://google.com" %
|
||||
{"user": self.ssh_user, "ip": db_ip})
|
|
@ -1,379 +0,0 @@
|
|||
# Copyright 2014
|
||||
# The Cloudscaling Group, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import netaddr
|
||||
|
||||
import tempest.cloudscaling.thirdparty.scenario.aws_compat.base as aws_base
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib.common.utils.linux import remote_client
|
||||
from tempest import test
|
||||
|
||||
import logging
|
||||
logging.getLogger('boto').setLevel(logging.CRITICAL)
|
||||
|
||||
|
||||
class VPC_Scenario(aws_base.BaseAWSTest):
|
||||
"""
|
||||
Reproduce 'VPC with Public and Private Subnets' scenario
|
||||
(http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Scenario2.html)
|
||||
"""
|
||||
class Context(object):
|
||||
vpc = None
|
||||
internet_gateway = None
|
||||
web_subnet = None
|
||||
db_subnet = None
|
||||
main_route_table = None
|
||||
custom_route_table = None
|
||||
web_security_group = None
|
||||
nat_security_group = None
|
||||
db_security_group = None
|
||||
web_instance = None
|
||||
db_instance = None
|
||||
nat_instance = None
|
||||
|
||||
@classmethod
|
||||
@test.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VPC_Scenario, cls).setUpClass()
|
||||
cls.ctx = cls.Context()
|
||||
cls.zone = cls.config.boto.aws_zone
|
||||
cfg = cls.config.cloudscaling
|
||||
cls.ssh_user = cfg.general_ssh_user_name
|
||||
cls.vpc_cidr = netaddr.IPNetwork(cfg.vpc_cidr)
|
||||
cls.web_subnet, cls.db_subnet = cls.vpc_cidr.subnet(
|
||||
cfg.vpc_subnet_prefix, 2)
|
||||
cls.test_client_cidr = netaddr.IPNetwork(cfg.test_client_cidr)
|
||||
cls.image_id = cls._prepare_image_id(cfg.general_image_name)
|
||||
cls.keypair = cls._prepare_key_pair()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
if cls.ctx is not None:
|
||||
for group in [cls.ctx.web_security_group,
|
||||
cls.ctx.nat_security_group,
|
||||
cls.ctx.db_security_group]:
|
||||
if not group:
|
||||
continue
|
||||
try:
|
||||
cls._revoke_security_group_linked_rules(group)
|
||||
except Exception:
|
||||
pass
|
||||
super(VPC_Scenario, cls).tearDownClass()
|
||||
|
||||
@classmethod
|
||||
def _revoke_security_group_linked_rules(cls, group):
|
||||
groups = cls.vpc_client.get_all_security_groups(group_ids=[group.id])
|
||||
if len(groups) == 0:
|
||||
return
|
||||
sg = groups[0]
|
||||
for rule in sg.rules:
|
||||
for grant in rule.grants:
|
||||
if not grant.cidr_ip:
|
||||
cls.vpc_client.revoke_security_group(
|
||||
group_id=sg.id,
|
||||
ip_protocol=rule.ip_protocol,
|
||||
from_port=rule.from_port,
|
||||
to_port=rule.to_port,
|
||||
src_security_group_group_id=grant.groupId)
|
||||
for rule in sg.rules_egress:
|
||||
for grant in rule.grants:
|
||||
if not grant.cidr_ip:
|
||||
cls.vpc_client.revoke_security_group_egress(
|
||||
sg.id,
|
||||
rule.ip_protocol,
|
||||
from_port=rule.from_port,
|
||||
to_port=rule.to_port,
|
||||
src_group_id=grant.groupId)
|
||||
|
||||
def test_000_create_vpc(self):
|
||||
"""Create VPC"""
|
||||
vpc = self.vpc_client.create_vpc(str(self.vpc_cidr))
|
||||
self.assertIsNotNone(vpc)
|
||||
self.assertTrue(vpc.id)
|
||||
self.addResourceCleanUp(self.vpc_client.delete_vpc, vpc.id)
|
||||
self.ctx.vpc = vpc
|
||||
|
||||
def test_001_create_internet_gateway(self):
|
||||
"""Create internet gateway"""
|
||||
ig = self.vpc_client.create_internet_gateway()
|
||||
self.assertIsNotNone(ig)
|
||||
self.assertTrue(ig.id)
|
||||
self.addResourceCleanUp(self._destroy_internet_gateway, ig)
|
||||
status = self.vpc_client.attach_internet_gateway(ig.id,
|
||||
self.ctx.vpc.id)
|
||||
self.assertTrue(status)
|
||||
self.ctx.internet_gateway = ig
|
||||
|
||||
def test_010_create_subnets(self):
|
||||
"""Create subnets"""
|
||||
sn = self.vpc_client.create_subnet(self.ctx.vpc.id,
|
||||
str(self.web_subnet),
|
||||
self.zone)
|
||||
self.assertIsNotNone(sn)
|
||||
self.assertTrue(sn.id)
|
||||
self.addResourceCleanUp(self.vpc_client.delete_subnet, sn.id)
|
||||
self.ctx.web_subnet = sn
|
||||
sn = self.vpc_client.create_subnet(self.ctx.vpc.id,
|
||||
str(self.db_subnet),
|
||||
self.zone)
|
||||
self.assertIsNotNone(sn)
|
||||
self.assertTrue(sn.id)
|
||||
self.addResourceCleanUp(self.vpc_client.delete_subnet, sn.id)
|
||||
self.ctx.db_subnet = sn
|
||||
|
||||
def test_020_get_main_route_table(self):
|
||||
"""Describe auto created route table"""
|
||||
rtables = self.vpc_client.get_all_route_tables(
|
||||
filters=[("vpc-id", self.ctx.vpc.id)])
|
||||
self.assertIsNotNone(rtables)
|
||||
self.assertEqual(1, len(rtables))
|
||||
self.ctx.main_route_table = rtables[0]
|
||||
|
||||
def test_025_create_custom_route_table(self):
|
||||
"""Create route table for web servers"""
|
||||
rtable = self.vpc_client.create_route_table(self.ctx.vpc.id)
|
||||
self.assertIsNotNone(rtable)
|
||||
self.assertTrue(rtable.id)
|
||||
self.addResourceCleanUp(self.vpc_client.delete_route_table, rtable.id)
|
||||
ig = self.ctx.internet_gateway
|
||||
status = self.vpc_client.create_route(rtable.id, "0.0.0.0/0",
|
||||
gateway_id=ig.id)
|
||||
self.assertTrue(status)
|
||||
association_id = self.vpc_client.associate_route_table(
|
||||
rtable.id, self.ctx.web_subnet.id)
|
||||
self.assertTrue(association_id)
|
||||
self.addResourceCleanUp(self.vpc_client.disassociate_route_table,
|
||||
association_id)
|
||||
self.ctx.custom_route_table = rtable
|
||||
|
||||
def test_050_create_security_groups(self):
|
||||
"""Create and tune security groups"""
|
||||
sg = self.vpc_client.create_security_group(
|
||||
data_utils.rand_name("WebServerSG-"),
|
||||
data_utils.rand_name("description "),
|
||||
self.ctx.vpc.id)
|
||||
self.assertIsNotNone(sg)
|
||||
self.assertTrue(sg.id)
|
||||
self.addResourceCleanUp(self._destroy_security_group_wait, sg)
|
||||
self.ctx.web_security_group = sg
|
||||
sg = self.vpc_client.create_security_group(
|
||||
data_utils.rand_name("NATSG-"),
|
||||
data_utils.rand_name("description "),
|
||||
self.ctx.vpc.id)
|
||||
self.assertIsNotNone(sg)
|
||||
self.assertTrue(sg.id)
|
||||
self.addResourceCleanUp(self._destroy_security_group_wait, sg)
|
||||
self.ctx.nat_security_group = sg
|
||||
sg = self.vpc_client.create_security_group(
|
||||
data_utils.rand_name("DBServerSG-"),
|
||||
data_utils.rand_name("description "),
|
||||
self.ctx.vpc.id)
|
||||
self.assertIsNotNone(sg)
|
||||
self.assertTrue(sg.id)
|
||||
self.addResourceCleanUp(self._destroy_security_group_wait, sg)
|
||||
self.ctx.db_security_group = sg
|
||||
|
||||
sg = self.ctx.web_security_group
|
||||
status = self.vpc_client.revoke_security_group_egress(
|
||||
sg.id, "-1", cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 1433, 1433,
|
||||
src_group_id=self.ctx.db_security_group.id)
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 3306, 3306,
|
||||
src_group_id=self.ctx.db_security_group.id)
|
||||
self.assertTrue(status)
|
||||
# NOTE(ft): especially for connectivity test
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 80, 80, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
# NOTE(ft): especially for connectivity test
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 22, 22,
|
||||
src_group_id=self.ctx.db_security_group.id)
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=80, to_port=80,
|
||||
cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=443, to_port=443,
|
||||
cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=22, to_port=22,
|
||||
cidr_ip=str(self.test_client_cidr))
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=3389,
|
||||
to_port=3389, cidr_ip=str(self.test_client_cidr))
|
||||
self.assertTrue(status)
|
||||
|
||||
sg = self.ctx.nat_security_group
|
||||
status = self.vpc_client.revoke_security_group_egress(
|
||||
sg.id, "-1", cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 80, 80, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 443, 443, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=80, to_port=80,
|
||||
cidr_ip=str(self.db_subnet))
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=443, to_port=443,
|
||||
cidr_ip=str(self.db_subnet))
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp", from_port=22, to_port=22,
|
||||
cidr_ip=str(self.test_client_cidr))
|
||||
self.assertTrue(status)
|
||||
|
||||
sg = self.ctx.db_security_group
|
||||
status = self.vpc_client.revoke_security_group_egress(
|
||||
sg.id, "-1", cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 80, 80, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group_egress(
|
||||
sg.id, "tcp", 443, 443, cidr_ip="0.0.0.0/0")
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp",
|
||||
from_port=1433,
|
||||
to_port=1433,
|
||||
src_security_group_group_id=self.ctx.web_security_group.id)
|
||||
self.assertTrue(status)
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp",
|
||||
from_port=3306,
|
||||
to_port=3306,
|
||||
src_security_group_group_id=self.ctx.web_security_group.id)
|
||||
self.assertTrue(status)
|
||||
# NOTE(ft): especially for connectivity test
|
||||
status = self.vpc_client.authorize_security_group(
|
||||
group_id=sg.id, ip_protocol="tcp",
|
||||
from_port=22,
|
||||
to_port=22,
|
||||
src_security_group_group_id=self.ctx.web_security_group.id)
|
||||
self.assertTrue(status)
|
||||
|
||||
def test_100_launch_nat_instance(self):
|
||||
"""Launch instances for NAT server"""
|
||||
reservation = self.vpc_client.run_instances(
|
||||
self.image_id,
|
||||
key_name=self.keypair.name,
|
||||
security_group_ids=[self.ctx.nat_security_group.id],
|
||||
instance_type=self.instance_type,
|
||||
placement=self.zone,
|
||||
subnet_id=self.ctx.web_subnet.id)
|
||||
self.assertIsNotNone(reservation)
|
||||
self.addResourceCleanUp(self.destroy_reservation, reservation)
|
||||
self.assertEqual(1, len(reservation.instances))
|
||||
instance = reservation.instances[0]
|
||||
if instance.state != "running":
|
||||
self.assertInstanceStateWait(instance, "running")
|
||||
self._prepare_public_ip(instance)
|
||||
status = self.vpc_client.modify_instance_attribute(
|
||||
instance.id, 'sourceDestCheck', False)
|
||||
self.assertTrue(status)
|
||||
|
||||
rtable = self.ctx.main_route_table
|
||||
status = self.vpc_client.create_route(rtable.id, "0.0.0.0/0",
|
||||
instance_id=instance.id)
|
||||
self.assertTrue(status)
|
||||
self.ctx.nat_instance = instance
|
||||
|
||||
def test_101_launch_instances(self):
|
||||
"""Launch instances for web server and db server"""
|
||||
reservation = self.vpc_client.run_instances(
|
||||
self.image_id,
|
||||
key_name=self.keypair.name,
|
||||
security_group_ids=[self.ctx.web_security_group.id],
|
||||
instance_type=self.instance_type,
|
||||
placement=self.zone,
|
||||
subnet_id=self.ctx.web_subnet.id)
|
||||
self.assertIsNotNone(reservation)
|
||||
self.addResourceCleanUp(self.destroy_reservation, reservation)
|
||||
self.assertEqual(1, len(reservation.instances))
|
||||
instance = reservation.instances[0]
|
||||
if instance.state != "running":
|
||||
self.assertInstanceStateWait(instance, "running")
|
||||
self._prepare_public_ip(instance)
|
||||
self.ctx.web_instance = instance
|
||||
|
||||
reservation = self.vpc_client.run_instances(
|
||||
self.image_id,
|
||||
key_name=self.keypair.name,
|
||||
security_group_ids=[self.ctx.db_security_group.id],
|
||||
instance_type=self.instance_type,
|
||||
placement=self.zone,
|
||||
subnet_id=self.ctx.db_subnet.id)
|
||||
self.assertIsNotNone(reservation)
|
||||
self.addResourceCleanUp(self.destroy_reservation, reservation)
|
||||
self.assertEqual(1, len(reservation.instances))
|
||||
instance = reservation.instances[0]
|
||||
if instance.state != "running":
|
||||
self.assertInstanceStateWait(instance, "running")
|
||||
self.ctx.db_instance = instance
|
||||
|
||||
def test_102_tune_nat_instance(self):
|
||||
"""Tune NAT in NAT instance"""
|
||||
instance = self.ctx.nat_instance
|
||||
address = instance.ip_address
|
||||
ssh = remote_client.RemoteClient(address,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
|
||||
# NOTE(ft): We must use tty mode, because some images (like Amazon
|
||||
# Linux) has restrictions (requiretty flag in /etc/sudoers)
|
||||
ssh_conn = ssh.ssh_client._get_ssh_connection()
|
||||
chan = ssh_conn.get_transport().open_session()
|
||||
chan.get_pty()
|
||||
chan.exec_command("sudo iptables -t nat -A POSTROUTING -s %s "
|
||||
"-o eth0 -j MASQUERADE" % str(self.vpc_cidr))
|
||||
chan.close()
|
||||
chan = ssh_conn.get_transport().open_session()
|
||||
chan.get_pty()
|
||||
chan.exec_command("sudo sysctl -w net.ipv4.ip_forward=1")
|
||||
chan.close()
|
||||
ssh_conn.close()
|
||||
|
||||
def test_200_check_connectivity(self):
|
||||
"""Check inside and outside connectivities"""
|
||||
web_ip = self.ctx.web_instance.ip_address
|
||||
db_ip = self.ctx.db_instance.private_ip_address
|
||||
ssh = remote_client.RemoteClient(web_ip,
|
||||
self.ssh_user,
|
||||
pkey=self.keypair.material)
|
||||
ssh.exec_command("curl -s http://google.com")
|
||||
|
||||
ssh_conn = ssh.ssh_client._get_ssh_connection()
|
||||
sftp = ssh_conn.open_sftp()
|
||||
fr = sftp.file("key.pem", 'wb')
|
||||
fr.set_pipelined(True)
|
||||
fr.write(self.keypair.material)
|
||||
fr.close()
|
||||
ssh_conn.close()
|
||||
ssh.exec_command('chmod 400 key.pem')
|
||||
ssh.exec_command("ssh -i key.pem -o UserKnownHostsFile=/dev/null "
|
||||
"-o StrictHostKeyChecking=no %(user)s@%(ip)s "
|
||||
"curl -s http://google.com" %
|
||||
{"user": self.ssh_user, "ip": db_ip})
|
|
@ -1,35 +0,0 @@
|
|||
# Copyright 2014
|
||||
# The Cloudscaling Group, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
logging.getLogger('boto').setLevel(logging.INFO)
|
||||
logging.getLogger('paramiko').setLevel(logging.WARNING)
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def detect_new_volume(proc_partitions, proc_partitions_new):
|
||||
devices = get_devices(proc_partitions)
|
||||
devices_new = get_devices(proc_partitions_new)
|
||||
devices_new -= devices
|
||||
return devices_new.pop()
|
||||
|
||||
|
||||
def get_devices(proc_partitions):
|
||||
devices = set()
|
||||
for line in proc_partitions:
|
||||
items = [item for item in line.split(' ') if len(item) > 0]
|
||||
if len(items) > 0:
|
||||
devices.add(items[3])
|
||||
|
||||
return devices
|
|
@ -1,52 +0,0 @@
|
|||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from tempest import config
|
||||
from tempest.test_discover import plugins
|
||||
|
||||
from ec2api.tests.functional import config_opts as aws_config
|
||||
|
||||
|
||||
class AWSTempestPlugin(plugins.TempestPlugin):
|
||||
def load_tests(self):
|
||||
base_path = os.path.split(os.path.dirname(os.path.dirname(
|
||||
os.path.dirname(os.path.abspath(__file__)))))[0]
|
||||
test_dir = "ec2api/tests/functional"
|
||||
full_test_dir = os.path.join(base_path, test_dir)
|
||||
return full_test_dir, base_path
|
||||
|
||||
def register_opts(self, conf):
|
||||
group_name = aws_config.service_available_group.name
|
||||
if group_name not in conf:
|
||||
config.register_opt_group(
|
||||
conf, aws_config.service_available_group,
|
||||
aws_config.ServiceAvailableGroup)
|
||||
else:
|
||||
for opt in aws_config.ServiceAvailableGroup:
|
||||
conf.register_opt(opt, group=group_name)
|
||||
|
||||
if aws_config.aws_group.name not in conf:
|
||||
config.register_opt_group(conf, aws_config.aws_group,
|
||||
aws_config.AWSGroup)
|
||||
|
||||
def get_opt_lists(self):
|
||||
return [
|
||||
(aws_config.service_available_group.name,
|
||||
aws_config.ServiceAvailableGroup),
|
||||
(aws_config.aws_group.name,
|
||||
aws_config.AWSGroup)
|
||||
]
|
|
@ -1,135 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class BaseScenarioTest(base.EC2TestCase):
|
||||
|
||||
def get_instance_ip(self, instance_id):
|
||||
instance = self.get_instance(instance_id)
|
||||
public_ip = instance.get('PublicIpAddress')
|
||||
if public_ip:
|
||||
return public_ip
|
||||
|
||||
is_vpc = 'VpcId' in instance
|
||||
alloc_id, public_ip = self.allocate_address(is_vpc)
|
||||
|
||||
kwargs = {'InstanceId': instance_id}
|
||||
if is_vpc:
|
||||
kwargs['AllocationId'] = alloc_id
|
||||
else:
|
||||
kwargs['PublicIp'] = public_ip
|
||||
data = self.client.associate_address(*[], **kwargs)
|
||||
if is_vpc:
|
||||
self.addResourceCleanUp(self.client.disassociate_address,
|
||||
AssociationId=data['AssociationId'])
|
||||
self.get_address_assoc_waiter().wait_available(
|
||||
{'AllocationId': alloc_id})
|
||||
else:
|
||||
self.addResourceCleanUp(self.client.disassociate_address,
|
||||
PublicIp=public_ip)
|
||||
self.get_address_assoc_waiter().wait_available(
|
||||
{'PublicIp': public_ip})
|
||||
|
||||
return public_ip
|
||||
|
||||
def allocate_address(self, is_vpc):
|
||||
kwargs = dict()
|
||||
if is_vpc:
|
||||
kwargs['Domain'] = 'vpc'
|
||||
data = self.client.allocate_address(*[], **kwargs)
|
||||
alloc_id = data.get('AllocationId')
|
||||
public_ip = data['PublicIp']
|
||||
if is_vpc:
|
||||
self.addResourceCleanUp(self.client.release_address,
|
||||
AllocationId=alloc_id)
|
||||
else:
|
||||
self.addResourceCleanUp(self.client.release_address,
|
||||
PublicIp=public_ip)
|
||||
|
||||
return alloc_id, public_ip
|
||||
|
||||
def create_key_pair(self, key_name):
|
||||
data = self.client.create_key_pair(KeyName=key_name)
|
||||
self.addResourceCleanUp(self.client.delete_key_pair, KeyName=key_name)
|
||||
return data.get('KeyMaterial')
|
||||
|
||||
def create_standard_security_group(self):
|
||||
name = data_utils.rand_name('sgName')
|
||||
desc = data_utils.rand_name('sgDesc')
|
||||
kwargs = {'GroupName': name, 'Description': desc}
|
||||
self.client.create_security_group(*[], **kwargs)
|
||||
self.addResourceCleanUp(self.client.delete_security_group,
|
||||
GroupName=name)
|
||||
time.sleep(2)
|
||||
|
||||
kwargs = {
|
||||
'GroupName': name,
|
||||
'IpPermissions': [{
|
||||
'IpProtocol': 'icmp',
|
||||
'FromPort': -1,
|
||||
'ToPort': -1,
|
||||
'IpRanges': [{
|
||||
'CidrIp': '0.0.0.0/0'
|
||||
}],
|
||||
}, {
|
||||
'IpProtocol': 'tcp',
|
||||
'FromPort': 22,
|
||||
'ToPort': 22,
|
||||
'IpRanges': [{
|
||||
'CidrIp': '0.0.0.0/0'
|
||||
}],
|
||||
}]
|
||||
}
|
||||
self.client.authorize_security_group_ingress(*[], **kwargs)
|
||||
|
||||
return name
|
||||
|
||||
def prepare_vpc_default_security_group(self, vpc_id):
|
||||
data = self.client.describe_security_groups(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])
|
||||
self.assertEqual(1, len(data['SecurityGroups']))
|
||||
group_id = data['SecurityGroups'][0]['GroupId']
|
||||
kwargs = {
|
||||
'GroupId': group_id,
|
||||
'IpPermissions': [{
|
||||
'IpProtocol': '-1',
|
||||
'FromPort': -1,
|
||||
'ToPort': -1,
|
||||
'IpRanges': [{
|
||||
'CidrIp': '0.0.0.0/0'
|
||||
}],
|
||||
}]
|
||||
}
|
||||
self.client.authorize_security_group_ingress(*[], **kwargs)
|
||||
|
||||
def create_network_interface(self, subnet_id):
|
||||
data = self.client.create_network_interface(SubnetId=subnet_id)
|
||||
ni_id = data['NetworkInterface']['NetworkInterfaceId']
|
||||
self.addResourceCleanUp(self.client.delete_network_interface,
|
||||
NetworkInterfaceId=ni_id)
|
||||
self.get_network_interface_waiter().wait_available(ni_id)
|
||||
|
||||
return ni_id
|
|
@ -1,455 +0,0 @@
|
|||
# Copyright 2014
|
||||
# The Cloudscaling Group, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import math
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class EC2_EBSInstanceTuneBDM(base.EC2TestCase):
|
||||
"""Test change root device attributes at instance launch."""
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(EC2_EBSInstanceTuneBDM, cls).setUpClass()
|
||||
if not CONF.aws.ebs_image_id:
|
||||
raise cls.skipException('aws EBS image does not provided')
|
||||
cls.image_id = CONF.aws.ebs_image_id
|
||||
cls.zone = CONF.aws.aws_zone
|
||||
|
||||
data = cls.client.describe_images(ImageIds=[cls.image_id])
|
||||
assert 1 == len(data['Images'])
|
||||
image = data['Images'][0]
|
||||
cls.root_device_name = image['RootDeviceName']
|
||||
bdm = image['BlockDeviceMappings']
|
||||
bdm = [v for v in bdm if v['DeviceName'] == cls.root_device_name]
|
||||
assert 1 == len(bdm)
|
||||
ebs = bdm[0]['Ebs']
|
||||
cls.root_device_size = ebs.get('VolumeSize')
|
||||
if not cls.root_device_size:
|
||||
snapshotId = ebs.get('SnapshotId')
|
||||
data = cls.client.describe_snapshots(SnapshotIds=[snapshotId])
|
||||
assert 1 == len(data['Snapshots'])
|
||||
cls.root_device_size = data['Snapshots'][0]['VolumeSize']
|
||||
|
||||
@decorators.idempotent_id('2f51dd78-ff1e-494a-bcbc-f47580df17cb')
|
||||
def test_launch_ebs_instance_with_persistent_root_device(self):
|
||||
"""
|
||||
|
||||
Launch EBS-backed instance with left root device after termination
|
||||
"""
|
||||
instance_id = self.run_instance(ImageId=self.image_id,
|
||||
BlockDeviceMappings=[{'DeviceName': self.root_device_name,
|
||||
'Ebs': {'DeleteOnTermination': False}}])
|
||||
|
||||
bdt = self.get_instance_bdm(instance_id, self.root_device_name)
|
||||
self.assertIsNotNone(bdt)
|
||||
volume_id = bdt['Ebs'].get('VolumeId')
|
||||
res_clean_vol = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
|
||||
self.assertIsNotNone(volume_id)
|
||||
self.assertFalse(bdt['Ebs']['DeleteOnTermination'])
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(res_clean_vol)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
@decorators.idempotent_id('0c820ed3-2e2f-4384-9649-cea907f00bf4')
|
||||
def test_launch_ebs_instance_with_resized_root_device(self):
|
||||
"""Launch EBS-backed instance with resizing root device."""
|
||||
new_size = int(math.ceil(self.root_device_size * 1.1))
|
||||
|
||||
instance_id = self.run_instance(ImageId=self.image_id,
|
||||
BlockDeviceMappings=[{'DeviceName': self.root_device_name,
|
||||
'Ebs': {'VolumeSize': new_size}}])
|
||||
|
||||
bdt = self.get_instance_bdm(instance_id, self.root_device_name)
|
||||
self.assertIsNotNone(bdt)
|
||||
volume_id = bdt['Ebs'].get('VolumeId')
|
||||
self.assertIsNotNone(volume_id)
|
||||
self.assertTrue(bdt['Ebs']['DeleteOnTermination'])
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
volume = data['Volumes'][0]
|
||||
self.assertEqual(new_size, volume['Size'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
@decorators.idempotent_id('a0dbb3bd-167f-4f35-bb9d-aa53233e3123')
|
||||
def test_launch_ebs_instance_with_creating_blank_volume(self):
|
||||
"""Launch instance with creating blank volume."""
|
||||
device_name_prefix = base.get_device_name_prefix(self.root_device_name)
|
||||
device_name = device_name_prefix + 'b'
|
||||
|
||||
instance_id = self.run_instance(ImageId=self.image_id,
|
||||
BlockDeviceMappings=[{'DeviceName': device_name,
|
||||
'Ebs': {'VolumeSize': 1}}])
|
||||
|
||||
bdt = self.get_instance_bdm(instance_id, device_name)
|
||||
self.assertIsNotNone(bdt)
|
||||
volume_id = bdt['Ebs'].get('VolumeId')
|
||||
self.assertIsNotNone(volume_id)
|
||||
self.assertTrue(bdt['Ebs']['DeleteOnTermination'])
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
volume = data['Volumes'][0]
|
||||
self.assertEqual(1, volume['Size'])
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
|
||||
class EC2_EBSInstanceAttaching(base.EC2TestCase):
|
||||
"""
|
||||
|
||||
Launch instance with two attached volumes. One at first free slot (xxdb,
|
||||
other at some free slot (xxdh). Use full device name for the first and
|
||||
short device name for the second. Check used device names.
|
||||
Detach devices and reattach their back with same names. Check used device
|
||||
names again.
|
||||
Detach devices and attach their in next slots (xxdc and xxdi). First with
|
||||
full name, and second with short. Check useed device names.
|
||||
Sometimes this test case failed in AWS because volumes get attach state
|
||||
'busy'. Then it's need to give a pause and rerun test case.
|
||||
Some dublicate tests are hidden to less output information.
|
||||
"""
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(EC2_EBSInstanceAttaching, cls).setUpClass()
|
||||
|
||||
if not CONF.aws.run_incompatible_tests:
|
||||
raise cls.skipException('Decsribe returns full device name while '
|
||||
'we boot with short name.')
|
||||
|
||||
if not CONF.aws.ebs_image_id:
|
||||
raise cls.skipException('aws EBS image does not provided')
|
||||
cls.image_id = CONF.aws.ebs_image_id
|
||||
cls.zone = CONF.aws.aws_zone
|
||||
|
||||
data = cls.client.describe_images(ImageIds=[cls.image_id])
|
||||
assert 1 == len(data['Images'])
|
||||
image = data['Images'][0]
|
||||
root_device_name = image['RootDeviceName']
|
||||
|
||||
device_name_prefix = base.get_device_name_prefix(root_device_name)
|
||||
cls.full_device_name_prefix = device_name_prefix
|
||||
cls.short_device_name_prefix = device_name_prefix[len("/dev/"):]
|
||||
|
||||
data = cls.client.create_volume(AvailabilityZone=cls.zone,
|
||||
Size=1)
|
||||
cls.volume_id = data['VolumeId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_volume,
|
||||
VolumeId=cls.volume_id)
|
||||
cls.get_volume_waiter().wait_available(cls.volume_id)
|
||||
|
||||
data = cls.client.create_snapshot(VolumeId=cls.volume_id)
|
||||
cls.snapshot_id = data['SnapshotId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_snapshot,
|
||||
SnapshotId=cls.snapshot_id)
|
||||
cls.get_snapshot_waiter().wait_available(cls.snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
instance_type = CONF.aws.instance_type
|
||||
cls.device1_name = cls.full_device_name_prefix + "d"
|
||||
cls.device2_name = cls.short_device_name_prefix + "h"
|
||||
data = cls.client.run_instances(
|
||||
ImageId=cls.image_id, InstanceType=instance_type,
|
||||
Placement={'AvailabilityZone': cls.zone}, MinCount=1, MaxCount=1,
|
||||
BlockDeviceMappings=[{'DeviceName': cls.device1_name,
|
||||
'Ebs': {'SnapshotId': cls.snapshot_id,
|
||||
'DeleteOnTermination': True}},
|
||||
{'DeviceName': cls.device2_name,
|
||||
'Ebs': {'SnapshotId': cls.snapshot_id,
|
||||
'DeleteOnTermination': True}}])
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
cls.instance_id = instance_id
|
||||
cls.addResourceCleanUpStatic(cls.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
cls.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
data = cls.client.describe_instances(InstanceIds=[instance_id])
|
||||
assert 1 == len(data.get('Reservations', []))
|
||||
instances = data['Reservations'][0].get('Instances', [])
|
||||
assert 1 == len(instances)
|
||||
instance = instances[0]
|
||||
bdms = instance['BlockDeviceMappings']
|
||||
for bdt in bdms:
|
||||
if bdt['DeviceName'] == cls.device1_name:
|
||||
cls.volume_id1 = bdt['Ebs']['VolumeId']
|
||||
if bdt['DeviceName'] == cls.device2_name:
|
||||
cls.volume_id2 = bdt['Ebs']['VolumeId']
|
||||
assert cls.volume_id1
|
||||
assert cls.volume_id2
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(EC2_EBSInstanceAttaching, cls).tearDownClass()
|
||||
# NOTE(andrey-mp): Amazon resets flag DeleteOnTermination after
|
||||
# reattaching volume, so we need delete them manually
|
||||
for volume_id in [cls.volume_id1, cls.volume_id2]:
|
||||
try:
|
||||
cls.cleanUpItem(cls.client.delete_volume, [],
|
||||
{'VolumeId': volume_id})
|
||||
except BaseException:
|
||||
LOG.exception('EBSInstanceAttaching.tearDownClass failure')
|
||||
|
||||
def _test_attaching(self, volume_id, device_name, device_prefix,
|
||||
new_device_name_letter):
|
||||
self.client.detach_volume(VolumeId=volume_id)
|
||||
clean_v = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_delete(volume_id)
|
||||
|
||||
bdt = self.get_instance_bdm(self.instance_id, device_name)
|
||||
self.assertIsNone(bdt)
|
||||
|
||||
self.client.attach_volume(InstanceId=self.instance_id,
|
||||
VolumeId=volume_id,
|
||||
Device=device_name)
|
||||
self.cancelResourceCleanUp(clean_v)
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id, final_set=('attached'))
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
self.assertEqual('in-use', data['Volumes'][0]['State'])
|
||||
|
||||
bdt = self.get_instance_bdm(self.instance_id, device_name)
|
||||
self.assertIsNotNone(bdt)
|
||||
|
||||
self.client.detach_volume(VolumeId=volume_id)
|
||||
clean_v = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_delete(volume_id)
|
||||
|
||||
bdt = self.get_instance_bdm(self.instance_id, device_name)
|
||||
self.assertIsNone(bdt)
|
||||
|
||||
new_device_name = device_prefix + new_device_name_letter
|
||||
self.client.attach_volume(InstanceId=self.instance_id,
|
||||
VolumeId=volume_id,
|
||||
Device=new_device_name)
|
||||
self.cancelResourceCleanUp(clean_v)
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id, final_set=('attached'))
|
||||
|
||||
data = self.client.describe_volumes(VolumeIds=[volume_id])
|
||||
self.assertEqual(1, len(data['Volumes']))
|
||||
self.assertEqual('in-use', data['Volumes'][0]['State'])
|
||||
|
||||
bdt = self.get_instance_bdm(self.instance_id, new_device_name)
|
||||
self.assertIsNotNone(bdt)
|
||||
|
||||
@decorators.idempotent_id('2176d935-5254-4e2a-9eb4-fc899f63c530')
|
||||
def test_attaching_by_full_name(self):
|
||||
"""Attach and reattach device by full name."""
|
||||
self._test_attaching(self.volume_id1, self.device1_name,
|
||||
self.full_device_name_prefix, "e")
|
||||
|
||||
@decorators.idempotent_id('43af092e-3f04-45a7-bec7-8da39cde1f4c')
|
||||
def test_attaching_by_short_name(self):
|
||||
"""Attach and reattach device by short name."""
|
||||
self._test_attaching(self.volume_id2, self.device2_name,
|
||||
self.short_device_name_prefix, "i")
|
||||
|
||||
|
||||
class EC2_EBSInstanceSnapshot(base.EC2TestCase):
|
||||
"""
|
||||
|
||||
Launch EBS-backed image, snapshot root device, register image,
|
||||
and launch another instance from the image
|
||||
(http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/
|
||||
instance-launch-snapshot.html)
|
||||
"""
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(EC2_EBSInstanceSnapshot, cls).setUpClass()
|
||||
if not CONF.aws.ebs_image_id:
|
||||
raise cls.skipException('aws EBS image does not provided')
|
||||
cls.image_id = CONF.aws.ebs_image_id
|
||||
cls.zone = CONF.aws.aws_zone
|
||||
|
||||
@decorators.idempotent_id('07caac78-750c-48a1-975d-d3a6bd988108')
|
||||
def test_create_ebs_instance_snapshot(self):
|
||||
"""Create snapshot of EBS-backed instance and check it."""
|
||||
|
||||
instance_id = self.run_instance(ImageId=self.image_id)
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
bdt = self.get_instance_bdm(instance_id, None)
|
||||
self.assertIsNotNone(bdt)
|
||||
volume_id = bdt['Ebs'].get('VolumeId')
|
||||
self.assertIsNotNone(volume_id)
|
||||
|
||||
self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
data = self.client.create_snapshot(VolumeId=volume_id)
|
||||
snapshot_id = data['SnapshotId']
|
||||
self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
kwargs = {
|
||||
'Name': data_utils.rand_name('ebs-ami'),
|
||||
'RootDeviceName': instance['RootDeviceName'],
|
||||
'BlockDeviceMappings': [{'DeviceName': instance['RootDeviceName'],
|
||||
'Ebs': {'SnapshotId': snapshot_id,
|
||||
'DeleteOnTermination': True}}]
|
||||
}
|
||||
if 'Architecture' in instance:
|
||||
kwargs['Architecture'] = instance['Architecture']
|
||||
if 'KernelId' in instance:
|
||||
kwargs['KernelId'] = instance['KernelId']
|
||||
if 'RamdiskId' in instance:
|
||||
kwargs['RamdiskId'] = instance['RamdiskId']
|
||||
data = self.client.register_image(*[], **kwargs)
|
||||
image_id = data['ImageId']
|
||||
clean_i = self.addResourceCleanUp(self.client.deregister_image,
|
||||
ImageId=image_id)
|
||||
self.get_image_waiter().wait_available(image_id)
|
||||
|
||||
instance_id = self.run_instance(ImageId=image_id)
|
||||
|
||||
# NOTE(andrey-mp): if instance will run then test will pass
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.client.deregister_image(ImageId=image_id)
|
||||
self.cancelResourceCleanUp(clean_i)
|
||||
|
||||
|
||||
class EC2_EBSInstanceResizeRootDevice(base.EC2TestCase):
|
||||
"""
|
||||
|
||||
Launch EBS-backed instance, stop instance, detach root volume, snapshot it,
|
||||
create volume from snapshot with increased size, attach new root volume,
|
||||
start instance
|
||||
(http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-expand-volume.html)
|
||||
"""
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(EC2_EBSInstanceResizeRootDevice, cls).setUpClass()
|
||||
if not CONF.aws.ebs_image_id:
|
||||
raise cls.skipException('aws EBS image does not provided')
|
||||
cls.image_id = CONF.aws.ebs_image_id
|
||||
cls.zone = CONF.aws.aws_zone
|
||||
|
||||
@decorators.idempotent_id('0ea1dee6-c2c3-4cad-9676-5bf6e7ae54a8')
|
||||
@testtools.skipUnless(
|
||||
CONF.aws.run_incompatible_tests,
|
||||
"Error from nova: "
|
||||
"Unexpected Forbidden raised: Can't detach root device volume")
|
||||
def test_resize_root_ebs_device(self):
|
||||
"""Resize root device of launched instance."""
|
||||
clean_dict = dict()
|
||||
instance_id = self.run_instance(clean_dict=clean_dict,
|
||||
ImageId=self.image_id)
|
||||
res_clean = clean_dict['instance']
|
||||
instance = self.get_instance(instance_id)
|
||||
|
||||
bdt = self.get_instance_bdm(instance_id, None)
|
||||
self.assertIsNotNone(bdt)
|
||||
volume_id = bdt['Ebs'].get('VolumeId')
|
||||
self.assertIsNotNone(volume_id)
|
||||
|
||||
self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
self.client.detach_volume(VolumeId=volume_id)
|
||||
clean_v = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
self.get_volume_attachment_waiter().wait_delete(volume_id)
|
||||
|
||||
data = self.client.create_snapshot(VolumeId=volume_id)
|
||||
snapshot_id = data['SnapshotId']
|
||||
clean_s = self.addResourceCleanUp(self.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
self.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
|
||||
new_size = int(math.ceil(data['VolumeSize'] * 1.1))
|
||||
data = self.client.create_volume(AvailabilityZone=self.zone,
|
||||
Size=new_size,
|
||||
SnapshotId=snapshot_id)
|
||||
volume_id2 = data['VolumeId']
|
||||
clean_v2 = self.addResourceCleanUp(self.client.delete_volume,
|
||||
VolumeId=volume_id2)
|
||||
self.get_volume_waiter().wait_available(volume_id2)
|
||||
|
||||
self.client.delete_snapshot(SnapshotId=snapshot_id)
|
||||
self.cancelResourceCleanUp(clean_s)
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id)
|
||||
self.cancelResourceCleanUp(clean_v)
|
||||
self.get_volume_waiter().wait_delete(volume_id)
|
||||
|
||||
self.client.attach_volume(
|
||||
InstanceId=instance_id, VolumeId=volume_id2,
|
||||
Device=instance['RootDeviceName'])
|
||||
self.get_volume_attachment_waiter().wait_available(
|
||||
volume_id2, final_set=('attached'))
|
||||
|
||||
# NOTE(andrey-mp): move this cleanup operation to the end of trash
|
||||
# (it will remove first)
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
res_clean = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
|
||||
self.client.start_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
# NOTE(andrey-mp): if instance will run then test will pass
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(res_clean)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.client.delete_volume(VolumeId=volume_id2)
|
||||
self.cancelResourceCleanUp(clean_v2)
|
|
@ -1,95 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib.common import ssh
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
from ec2api.tests.functional.scenario import base as scenario_base
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class InstanceRestartTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
@decorators.idempotent_id('8ae801a5-3e4a-4a34-903a-45e34ff9eccd')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.run_long_tests, 'Slow test has skipped.')
|
||||
@testtools.skipUnless(CONF.aws.image_id_ubuntu,
|
||||
"ubuntu image id is not defined")
|
||||
def test_stop_start_instance(self):
|
||||
key_name = data_utils.rand_name('testkey')
|
||||
pkey = self.create_key_pair(key_name)
|
||||
sec_group_name = self.create_standard_security_group()
|
||||
instance_id = self.run_instance(KeyName=key_name,
|
||||
ImageId=CONF.aws.image_id_ubuntu,
|
||||
SecurityGroups=[sec_group_name])
|
||||
|
||||
ip_address = self.get_instance_ip(instance_id)
|
||||
ssh_client = ssh.Client(ip_address, CONF.aws.image_user_ubuntu,
|
||||
pkey=pkey)
|
||||
ssh_client.exec_command('last -x')
|
||||
|
||||
self.client.stop_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('stopped'))
|
||||
|
||||
self.client.start_instances(InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
# Amazon can change auto-assigned public ip
|
||||
ip_address = self.get_instance_ip(instance_id)
|
||||
ssh_client = ssh.Client(ip_address, CONF.aws.image_user_ubuntu,
|
||||
pkey=pkey)
|
||||
data = ssh_client.exec_command('last -x')
|
||||
self.assertIn("shutdown", data)
|
||||
|
||||
@decorators.idempotent_id('ae1cce79-882c-4f37-b9e9-2f7156712721')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.run_long_tests, 'Slow test has skipped.')
|
||||
@testtools.skipUnless(CONF.aws.image_id_ubuntu,
|
||||
"ubuntu image id is not defined")
|
||||
def test_reboot_instance(self):
|
||||
key_name = data_utils.rand_name('testkey')
|
||||
pkey = self.create_key_pair(key_name)
|
||||
sec_group_name = self.create_standard_security_group()
|
||||
instance_id = self.run_instance(KeyName=key_name,
|
||||
ImageId=CONF.aws.image_id_ubuntu,
|
||||
SecurityGroups=[sec_group_name])
|
||||
ip_address = self.get_instance_ip(instance_id)
|
||||
|
||||
ssh_client = ssh.Client(ip_address, CONF.aws.image_user_ubuntu,
|
||||
pkey=pkey)
|
||||
last_lines = ssh_client.exec_command('last -x').split('\n')
|
||||
|
||||
self.client.reboot_instances(InstanceIds=[instance_id])
|
||||
|
||||
def _last_state():
|
||||
current = ssh_client.exec_command('last -x').split('\n')
|
||||
if len(current) > len(last_lines):
|
||||
return
|
||||
raise Exception()
|
||||
|
||||
waiter = base.EC2Waiter(_last_state)
|
||||
waiter.wait_no_exception()
|
||||
|
||||
data = ssh_client.exec_command('last -x')
|
||||
self.assertIn("shutdown", data)
|
|
@ -1,180 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import base64
|
||||
import os
|
||||
|
||||
from oslo_log import log
|
||||
import six
|
||||
from tempest.lib.common import ssh
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
from ec2api.tests.functional.scenario import base as scenario_base
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
PRIVATE_KEY_MATERIAL = (
|
||||
'-----BEGIN RSA PRIVATE KEY-----\n'
|
||||
'MIIEpAIBAAKCAQEAxkaf7L0BoNmyzlWPh29WPsaUP2+kV2vuoCQrO2FWliV8OOUP\n'
|
||||
'+OIPvqRF+XtcCWc5LIQrSzKnitazJmoUO1m/J7fwxv2Qf2kbKVLrLqP7AUh1pAgG\n'
|
||||
'DUqnBS8F5+2kPsMRKAE+xz1uJDpnP5ktIzpn1hWDVCoG80/jP7d7YSi0KlIYMHVx\n'
|
||||
'E3WegrQ5IWw/BI62LR1KOe2YBSrv1n9SDc2w69QbfrnsZOpNKAnv/+G7LIqeHKP1\n'
|
||||
'G5YMh2iWtEzdDgHqWa+HvtifhS3AzdtG7zgpmpwq8JYheYXLC+S/qxdZSGFx3p5s\n'
|
||||
'JKr7kiAcxWqTsYEEtJdbYKDYfmu1e+k5hP901wIDAQABAoIBAFJkDJaSX7fYXq3Q\n'
|
||||
'7giIYl1JpVbK7I6LQih3fyN4qkNQJlN6E+4G+iXtG0q1USRzKVXvQhJIZUiTOPSQ\n'
|
||||
'hgG3pHA7xijaOw5GvcupMiM6btY0pvXXg7RIPikwRhL/NA4Efv+RrOWcCEWzoy3R\n'
|
||||
'V+lYnsdePyldIXA/1R2n//P6twsSP+055XCabN/HVEJMtYmeVnZsoffRgos5cDlT\n'
|
||||
'afpq29W93kI7kXTDIlNxdQXzOa1rKqmUK/nBf0caMwaGy9Di9s3OP8M+Xs4Y/L0b\n'
|
||||
'+QOuILwBNjMMj3yqdDyDT698kQoO0oX458L70MUk660PItdaqyPT1KAaCIz7xTFJ\n'
|
||||
'7OQM10kCgYEA+ES8irwqkkSocZ0QQzCR5qxIp3cVrnw1kaaqWuZOgojMPvRpzFJO\n'
|
||||
'x4IB6VbvcpPPqHBhCGuJYIDYXuM1Ke0YR4TllNec9ZvSPvUYFNNQLeXmAyaWKtIE\n'
|
||||
'91BoONyEMsbpWr/hsG60y4cFoqNZVqILHTNS48TMVtB4Lv8IgOv3OVsCgYEAzHNV\n'
|
||||
'YZzUMdBN5rEuNwJ5NtModung7H08g9jOiGHMo0ZQvhKhFYgieQmJRGXOhMpbNPL4\n'
|
||||
'9RLQjAVr4mrFdk+sDqVmscqu07q2/jjT1U1x2rprBpzckOvmmw7TKveiGfgcwqZ+\n'
|
||||
'Qs3tWoiLc8m74loJyT/7c0tpyZxjbPJL7jVQzzUCgYEAqnNuywWDaObwiwhduPOo\n'
|
||||
'yCmyvB87aI9oq/Y0cbI7Zs2LBRIDbT95TOqKa2y/evfWk3uMcx55tCLh6sutnXpl\n'
|
||||
't/ybLwSVg98Wixj1Dp9CJjD4KWOdqAqHVFEFLTzhGoeMgTzKM7reL/okuVPTK3KX\n'
|
||||
'lNW+7BgafuQkD4gTi4f2NY8CgYEAiUNlr4N7c3ZG1vtd69DdUNGz+SJMwHnUhzCo\n'
|
||||
'eSgwG+65huM7AxnDC0A7yJARd1Xkpkf6nY9kNJ3vMLQ+npAfFDY4HGXXuo9BDK1a\n'
|
||||
'i3rTVeaStH3cF/BJgxEQ9WgMjSLnLEhbvL5E/ONvvO1UF0QcDeHHEEExZQp6Nkr2\n'
|
||||
'b5ecCYECgYBtL4kr0qttoowbfj+pXjwiJjbwb6GBaMBVNQTtJBKdl5AeyDm9qh2o\n'
|
||||
'vF60vnm+wWFfUs8nlvPMT/FNHwjHtFOBLPhw6tUcyrzh1ba4v/FE40FW4NxgqSK/\n'
|
||||
'VS0+XhPxet+E9kXjMMrVUaDrHHR2+zM5OyOLG0a/JIcsFuf7qZgAMQ==\n'
|
||||
'-----END RSA PRIVATE KEY-----'
|
||||
)
|
||||
PUBLIC_KEY_MATERIAL = (
|
||||
'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGRp/svQGg2bLOVY+Hb1Y+xpQ/'
|
||||
'b6RXa+6gJCs7YVaWJXw45Q/44g++pEX5e1wJZzkshCtLMqeK1rMmahQ7Wb8nt/DG'
|
||||
'/ZB/aRspUusuo/sBSHWkCAYNSqcFLwXn7aQ+wxEoAT7HPW4kOmc/mS0jOmfWFYNU'
|
||||
'KgbzT+M/t3thKLQqUhgwdXETdZ6CtDkhbD8EjrYtHUo57ZgFKu/Wf1INzbDr1Bt+'
|
||||
'uexk6k0oCe//4bssip4co/UblgyHaJa0TN0OAepZr4e+2J+FLcDN20bvOCmanCrw'
|
||||
'liF5hcsL5L+rF1lIYXHenmwkqvuSIBzFapOxgQS0l1tgoNh+a7V76TmE/3TX '
|
||||
'ubuntu@test.com'
|
||||
)
|
||||
|
||||
|
||||
class InstancesTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
@decorators.idempotent_id('c25defc4-b075-4794-9fa6-3b67353c4079')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_metadata(self):
|
||||
key_name = data_utils.rand_name('testkey')
|
||||
self.client.import_key_pair(KeyName=key_name,
|
||||
PublicKeyMaterial=PUBLIC_KEY_MATERIAL)
|
||||
self.addResourceCleanUp(self.client.delete_key_pair, KeyName=key_name)
|
||||
|
||||
sec_group_name = self.create_standard_security_group()
|
||||
user_data = six.text_type(data_utils.rand_uuid()) + six.unichr(1071)
|
||||
instance_id = self.run_instance(KeyName=key_name, UserData=user_data,
|
||||
SecurityGroups=[sec_group_name])
|
||||
|
||||
data = self.client.describe_instance_attribute(
|
||||
InstanceId=instance_id, Attribute='userData')
|
||||
self.assertEqual(
|
||||
data['UserData']['Value'],
|
||||
base64.b64encode(user_data.encode("utf-8")).decode("utf-8"))
|
||||
|
||||
ip_address = self.get_instance_ip(instance_id)
|
||||
|
||||
ssh_client = ssh.Client(ip_address, CONF.aws.image_user,
|
||||
pkey=PRIVATE_KEY_MATERIAL)
|
||||
|
||||
url = 'http://169.254.169.254'
|
||||
data = ssh_client.exec_command('curl %s/latest/user-data' % url)
|
||||
if isinstance(data, six.binary_type):
|
||||
data = data.decode("utf-8")
|
||||
self.assertEqual(user_data, data)
|
||||
|
||||
data = ssh_client.exec_command('curl %s/latest/meta-data/ami-id' % url)
|
||||
self.assertEqual(CONF.aws.image_id, data)
|
||||
|
||||
data = ssh_client.exec_command(
|
||||
'curl %s/latest/meta-data/public-keys/0/openssh-key' % url)
|
||||
# compare only keys. without 'sha-rsa' and owner
|
||||
self.assertEqual(PUBLIC_KEY_MATERIAL.split()[1], data.split()[1])
|
||||
|
||||
@decorators.idempotent_id('9fd254b1-dad1-4bb6-959f-f2cf937873c7')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_compare_console_output(self):
|
||||
key_name = data_utils.rand_name('testkey')
|
||||
pkey = self.create_key_pair(key_name)
|
||||
sec_group_name = self.create_standard_security_group()
|
||||
instance_id = self.run_instance(KeyName=key_name,
|
||||
SecurityGroups=[sec_group_name])
|
||||
|
||||
data_to_check = data_utils.rand_uuid()
|
||||
ip_address = self.get_instance_ip(instance_id)
|
||||
ssh_client = ssh.Client(ip_address, CONF.aws.image_user, pkey=pkey)
|
||||
cmd = 'sudo sh -c "echo \\"%s\\" >/dev/console"' % data_to_check
|
||||
ssh_client.exec_command(cmd)
|
||||
|
||||
waiter = base.EC2Waiter(self.client.get_console_output)
|
||||
waiter.wait_no_exception(InstanceId=instance_id)
|
||||
|
||||
def _compare_console_output():
|
||||
data = self.client.get_console_output(InstanceId=instance_id)
|
||||
self.assertEqual(instance_id, data['InstanceId'])
|
||||
self.assertIsNotNone(data['Timestamp'])
|
||||
self.assertIn('Output', data)
|
||||
self.assertIn(data_to_check, data['Output'])
|
||||
|
||||
waiter = base.EC2Waiter(_compare_console_output)
|
||||
waiter.wait_no_exception()
|
||||
|
||||
@decorators.idempotent_id('df1bb8f2-193c-46ba-aa99-3981bbc367db')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.ami_image_location, "Image is absent in S3")
|
||||
def test_run_and_ping_registered_image(self):
|
||||
image_name = data_utils.rand_name("ami-name")
|
||||
data = self.client.register_image(
|
||||
Name=image_name, ImageLocation=CONF.aws.ami_image_location)
|
||||
image_id = data['ImageId']
|
||||
self.addResourceCleanUp(self.client.deregister_image, ImageId=image_id)
|
||||
self.get_image_waiter().wait_available(image_id)
|
||||
|
||||
# launch this image
|
||||
sec_group_name = self.create_standard_security_group()
|
||||
instance_id = self.run_instance(ImageId=image_id,
|
||||
SecurityGroups=[sec_group_name])
|
||||
|
||||
waiter = base.EC2Waiter(self.client.get_console_output)
|
||||
waiter.wait_no_exception(InstanceId=instance_id)
|
||||
|
||||
def _compare_console_output():
|
||||
data = self.client.get_console_output(InstanceId=instance_id)
|
||||
self.assertEqual(instance_id, data['InstanceId'])
|
||||
self.assertIsNotNone(data['Timestamp'])
|
||||
self.assertIn('Output', data)
|
||||
self.assertNotEqual('', data['Output'])
|
||||
|
||||
waiter = base.EC2Waiter(_compare_console_output)
|
||||
waiter.wait_no_exception()
|
||||
|
||||
# check ping
|
||||
ip_address = self.get_instance_ip(instance_id)
|
||||
|
||||
def _ping():
|
||||
response = os.system("ping -c 1 " + ip_address + " > /dev/null")
|
||||
self.assertEqual(0, response)
|
||||
|
||||
waiter = base.EC2Waiter(_ping)
|
||||
waiter.wait_no_exception()
|
|
@ -1,170 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import netaddr
|
||||
from oslo_log import log
|
||||
from tempest.lib.common import ssh
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
from tempest.lib import exceptions
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
from ec2api.tests.functional.scenario import base as scenario_base
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class InstancesInVPCTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
def _test_instances(self, subnet_size):
|
||||
cidr = netaddr.IPNetwork('10.20.0.0/8')
|
||||
cidr.prefixlen = subnet_size
|
||||
vpc_id, subnet_id = self.create_vpc_and_subnet(str(cidr))
|
||||
gw_id = self.create_and_attach_internet_gateway(vpc_id)
|
||||
self.prepare_vpc_default_security_group(vpc_id)
|
||||
self.prepare_route(vpc_id, gw_id)
|
||||
|
||||
key_name = data_utils.rand_name('testkey')
|
||||
pkey = self.create_key_pair(key_name)
|
||||
|
||||
first_ip = str(netaddr.IPAddress(cidr.first + 4))
|
||||
last_ip = str(netaddr.IPAddress(cidr.last - 1))
|
||||
instance_id1 = self.run_instance(KeyName=key_name, SubnetId=subnet_id,
|
||||
PrivateIpAddress=first_ip)
|
||||
instance_id2 = self.run_instance(KeyName=key_name, SubnetId=subnet_id,
|
||||
PrivateIpAddress=last_ip)
|
||||
instance = self.get_instance(instance_id1)
|
||||
self.assertEqual(first_ip, instance['PrivateIpAddress'])
|
||||
instance = self.get_instance(instance_id2)
|
||||
self.assertEqual(last_ip, instance['PrivateIpAddress'])
|
||||
|
||||
ip_address = self.get_instance_ip(instance_id1)
|
||||
ssh_client = ssh.Client(ip_address, CONF.aws.image_user, pkey=pkey)
|
||||
|
||||
waiter = base.EC2Waiter(ssh_client.exec_command)
|
||||
waiter.wait_no_exception('ping %s -c 1' % last_ip)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('b986708e-9559-493d-aeb3-97fc992a65cf')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_instances_in_min_subnet(self):
|
||||
self._test_instances(28)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('7bf8e80c-cd05-4ccb-944a-e4b09825d151')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_instances_in_max_subnet(self):
|
||||
self._test_instances(16)
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('9c3a8066-68b2-4bd0-85e0-6d4a0d7cb053')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_default_gateway(self):
|
||||
novpc_group = self.create_standard_security_group()
|
||||
novpc_instance_id = self.run_instance(SecurityGroups=[novpc_group])
|
||||
ping_destination = self.get_instance_ip(novpc_instance_id)
|
||||
|
||||
data = self.client.create_vpc(CidrBlock='10.10.0.0/16')
|
||||
vpc_id = data['Vpc']['VpcId']
|
||||
self.addResourceCleanUp(self.client.delete_vpc, VpcId=vpc_id)
|
||||
self.get_vpc_waiter().wait_available(vpc_id)
|
||||
|
||||
data = self.client.create_subnet(
|
||||
VpcId=vpc_id, CidrBlock='10.10.1.0/24',
|
||||
AvailabilityZone=CONF.aws.aws_zone)
|
||||
subnet_1_id = data['Subnet']['SubnetId']
|
||||
self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_1_id)
|
||||
|
||||
data = self.client.create_subnet(
|
||||
VpcId=vpc_id, CidrBlock='10.10.2.0/24',
|
||||
AvailabilityZone=CONF.aws.aws_zone)
|
||||
subnet_2_id = data['Subnet']['SubnetId']
|
||||
self.addResourceCleanUp(self.client.delete_subnet,
|
||||
SubnetId=subnet_2_id)
|
||||
|
||||
data = self.client.create_internet_gateway()
|
||||
gw_id = data['InternetGateway']['InternetGatewayId']
|
||||
self.addResourceCleanUp(self.client.delete_internet_gateway,
|
||||
InternetGatewayId=gw_id)
|
||||
data = self.client.attach_internet_gateway(VpcId=vpc_id,
|
||||
InternetGatewayId=gw_id)
|
||||
self.addResourceCleanUp(self.client.detach_internet_gateway,
|
||||
VpcId=vpc_id, InternetGatewayId=gw_id)
|
||||
|
||||
self.prepare_route(vpc_id, gw_id)
|
||||
|
||||
data = self.client.create_route_table(VpcId=vpc_id)
|
||||
rt_id = data['RouteTable']['RouteTableId']
|
||||
self.addResourceCleanUp(self.client.delete_route_table,
|
||||
RouteTableId=rt_id)
|
||||
data = self.client.associate_route_table(RouteTableId=rt_id,
|
||||
SubnetId=subnet_2_id)
|
||||
assoc_id = data['AssociationId']
|
||||
self.addResourceCleanUp(self.client.disassociate_route_table,
|
||||
AssociationId=assoc_id)
|
||||
|
||||
self.prepare_vpc_default_security_group(vpc_id)
|
||||
key_name = data_utils.rand_name('testkey')
|
||||
pkey = self.create_key_pair(key_name)
|
||||
|
||||
instance_2_id = self.run_instance(KeyName=key_name,
|
||||
SubnetId=subnet_2_id)
|
||||
instance_1_id = self.run_instance(KeyName=key_name,
|
||||
SubnetId=subnet_1_id,
|
||||
UserData=pkey)
|
||||
ip_address = self.get_instance_ip(instance_1_id)
|
||||
ip_private_address_1 = self.get_instance(
|
||||
instance_1_id)['PrivateIpAddress']
|
||||
ip_private_address_2 = self.get_instance(
|
||||
instance_2_id)['PrivateIpAddress']
|
||||
|
||||
ssh_client = ssh.Client(ip_address, CONF.aws.image_user, pkey=pkey,
|
||||
channel_timeout=30)
|
||||
|
||||
ssh_client.exec_command(
|
||||
'curl http://169.254.169.254/latest/user-data > key.pem && '
|
||||
'chmod 400 key.pem')
|
||||
if 'cirros' in ssh_client.exec_command('cat /etc/issue'):
|
||||
ssh_client.exec_command(
|
||||
'dropbearconvert openssh dropbear key.pem key.db && '
|
||||
'mv key.db key.pem')
|
||||
extra_ssh_opts = '-y'
|
||||
else:
|
||||
extra_ssh_opts = ('-o UserKnownHostsFile=/dev/null '
|
||||
'-o StrictHostKeyChecking=no')
|
||||
|
||||
ssh_client.exec_command('ping -c 1 %s' % ip_private_address_2)
|
||||
ssh_client.exec_command('ping -c 1 %s' % ping_destination)
|
||||
remote_ping_template = (
|
||||
'ssh -i key.pem %(extra_opts)s %(user)s@%(ip)s '
|
||||
'ping -c 1 %%s' %
|
||||
{'extra_opts': extra_ssh_opts,
|
||||
'user': CONF.aws.image_user,
|
||||
'ip': ip_private_address_2})
|
||||
ssh_client.exec_command(remote_ping_template % ip_private_address_1)
|
||||
try:
|
||||
resp = ssh_client.exec_command(remote_ping_template %
|
||||
ping_destination)
|
||||
except exceptions.SSHExecCommandFailed:
|
||||
pass
|
||||
else:
|
||||
self.assertEqual('', resp)
|
|
@ -1,410 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
import botocore.exceptions
|
||||
from oslo_log import log
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
from ec2api.tests.functional.scenario import base as scenario_base
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class TagsPagingTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
# NOTE(andrey-mp): limit for tags for one resource in amazon
|
||||
TAGS_COUNT = 10
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(TagsPagingTest, cls).setUpClass()
|
||||
if 'amazon' in CONF.aws.ec2_url:
|
||||
raise cls.skipException('Paging is broken in Amazon.')
|
||||
|
||||
def _create_volume_and_tags(self):
|
||||
data = self.client.create_volume(
|
||||
Size=1, AvailabilityZone=CONF.aws.aws_zone)
|
||||
volume_id = data['VolumeId']
|
||||
self.addResourceCleanUp(self.client.delete_volume, VolumeId=volume_id)
|
||||
self.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
keys = list()
|
||||
for dummy in xrange(0, self.TAGS_COUNT):
|
||||
key = data_utils.rand_name('key')
|
||||
value = 'aaa' if dummy < 6 else 'bbb'
|
||||
data = self.client.create_tags(Resources=[volume_id],
|
||||
Tags=[{'Key': key, 'Value': value}])
|
||||
keys.append(key)
|
||||
|
||||
return volume_id, keys
|
||||
|
||||
@decorators.idempotent_id('8df6e612-07cd-466d-99de-9f37954a6c9a')
|
||||
def test_simple_tags_paging_with_many_results(self):
|
||||
volume_id = self._create_volume_and_tags()[0]
|
||||
|
||||
data = self.client.describe_tags(MaxResults=500,
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]}])
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
self.assertEqual(self.TAGS_COUNT, len(data['Tags']))
|
||||
|
||||
@decorators.idempotent_id('683883d5-9a94-43f2-a1eb-d193db0e44e9')
|
||||
def test_simple_tags_paging_with_min_results(self):
|
||||
volume_id = self._create_volume_and_tags()[0]
|
||||
|
||||
data = self.client.describe_tags(
|
||||
MaxResults=5,
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]},
|
||||
{'Name': 'tag-value', 'Values': ['aaa']}])
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
|
||||
@decorators.idempotent_id('1db8cc5a-d0b3-4e5f-b411-d84cfa4f21e0')
|
||||
def test_tags_paging_second_page_only_with_token(self):
|
||||
volume_id = self._create_volume_and_tags()[0]
|
||||
|
||||
data = self.client.describe_tags(
|
||||
MaxResults=5,
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]},
|
||||
{'Name': 'tag-value', 'Values': ['aaa']}])
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
data = self.client.describe_tags(
|
||||
NextToken=data['NextToken'],
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]},
|
||||
{'Name': 'tag-value', 'Values': ['aaa']}])
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
|
||||
@decorators.idempotent_id('a4d7b315-9616-4f9e-85b7-0f892e09a9a2')
|
||||
def test_tags_paging_with_const_filter(self):
|
||||
volume_id = self._create_volume_and_tags()[0]
|
||||
|
||||
data = self.client.describe_tags(
|
||||
MaxResults=5,
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]},
|
||||
{'Name': 'tag-value', 'Values': ['aaa']}])
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
data = self.client.describe_tags(
|
||||
MaxResults=5, NextToken=data['NextToken'],
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]},
|
||||
{'Name': 'tag-value', 'Values': ['aaa']}])
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
|
||||
@decorators.idempotent_id('ad4b793a-8231-4d30-8c26-43736b7b71e4')
|
||||
def test_tags_paging_with_differenet_filters(self):
|
||||
volume_id = self._create_volume_and_tags()[0]
|
||||
|
||||
data = self.client.describe_tags(
|
||||
MaxResults=5,
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]},
|
||||
{'Name': 'tag-value', 'Values': ['aaa']}])
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
data = self.client.describe_tags(
|
||||
MaxResults=5, NextToken=data['NextToken'],
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]}])
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
self.assertLessEqual(1, len(data['Tags']))
|
||||
|
||||
@decorators.idempotent_id('ec6d68bb-37f3-4c5c-b4c5-000d73fbc1bf')
|
||||
def test_tags_paging_with_tags_deletion(self):
|
||||
volume_id, keys = self._create_volume_and_tags()
|
||||
|
||||
data = self.client.describe_tags(MaxResults=5,
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]}])
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Tags'])
|
||||
for key in keys:
|
||||
self.client.delete_tags(Resources=[volume_id], Tags=[{'Key': key}])
|
||||
data = self.client.describe_tags(
|
||||
MaxResults=5, NextToken=data['NextToken'],
|
||||
Filters=[{'Name': 'resource-id', 'Values': [volume_id]}])
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertEmpty(data['Tags'])
|
||||
|
||||
@decorators.idempotent_id('37eb0597-998f-4744-8462-d56e5599dcd8')
|
||||
def test_invalid_max_results(self):
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_tags, MaxResults=4)
|
||||
|
||||
# NOTE(andrey-mp): value more than 1000 in not invalid
|
||||
# but amazon returns 1000 elements
|
||||
self.client.describe_tags(MaxResults=1100)
|
||||
|
||||
|
||||
class VolumesPagingTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
VOLUMES_COUNT = 6
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VolumesPagingTest, cls).setUpClass()
|
||||
if 'amazon' in CONF.aws.ec2_url:
|
||||
raise cls.skipException('Paging is broken in Amazon.')
|
||||
|
||||
zone = CONF.aws.aws_zone
|
||||
cls.ids = list()
|
||||
for dummy in xrange(0, cls.VOLUMES_COUNT):
|
||||
data = cls.client.create_volume(Size=1, AvailabilityZone=zone)
|
||||
volume_id = data['VolumeId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
cls.ids.append(volume_id)
|
||||
for volume_id in cls.ids:
|
||||
cls.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
@decorators.idempotent_id('d44ea940-d9ae-42a4-b3ce-add296a1678c')
|
||||
def test_simple_volumes_paging_with_many_results(self):
|
||||
data = self.client.describe_volumes(MaxResults=500)
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Volumes'])
|
||||
self.assertLessEqual(self.VOLUMES_COUNT, len(data['Volumes']))
|
||||
|
||||
@decorators.idempotent_id('9780c871-ee90-411c-b6ec-1e2f1785926b')
|
||||
def test_simple_volumes_paging_with_min_results(self):
|
||||
data = self.client.describe_volumes(MaxResults=5)
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Volumes'])
|
||||
|
||||
@decorators.idempotent_id('692684c4-62bc-457a-899a-07cc5382c9ab')
|
||||
def test_volumes_paging_second_page(self):
|
||||
data = self.client.describe_volumes(MaxResults=5)
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Volumes'])
|
||||
data = self.client.describe_volumes(
|
||||
MaxResults=5, NextToken=data['NextToken'])
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Volumes'])
|
||||
|
||||
@decorators.idempotent_id('83183fac-bb9b-4c36-8d23-84ed55c57015')
|
||||
def test_invalid_paging(self):
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_volumes, MaxResults=4)
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.describe_volumes,
|
||||
MaxResults=5, VolumeIds=[self.ids[0]])
|
||||
|
||||
@decorators.idempotent_id('2a777d78-9f0b-4ab0-a841-73dbaafae0dd')
|
||||
def test_volumes_paging_with_filters(self):
|
||||
data = self.client.describe_volumes(MaxResults=5,
|
||||
Filters=[{'Name': 'volume-id', 'Values': [self.ids[0]]}])
|
||||
self.assertNotEmpty(data['Volumes'])
|
||||
if 'NextToken' in data:
|
||||
# Amazon way
|
||||
data = self.client.describe_volumes(
|
||||
MaxResults=5, NextToken=data['NextToken'],
|
||||
Filters=[{'Name': 'volume-id', 'Values': [self.ids[0]]}])
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertEmpty(data['Volumes'])
|
||||
|
||||
data = self.client.describe_volumes(MaxResults=5,
|
||||
Filters=[{'Name': 'volume-id', 'Values': ['vol-*']}])
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Volumes'])
|
||||
data = self.client.describe_volumes(
|
||||
MaxResults=5, NextToken=data['NextToken'],
|
||||
Filters=[{'Name': 'volume-id', 'Values': ['vol-*']}])
|
||||
self.assertNotEmpty(data['Volumes'])
|
||||
|
||||
|
||||
class SnapshotPagingTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
SNAPSHOTS_COUNT = 6
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(SnapshotPagingTest, cls).setUpClass()
|
||||
if 'amazon' in CONF.aws.ec2_url:
|
||||
raise cls.skipException('Paging is broken in Amazon.')
|
||||
|
||||
zone = CONF.aws.aws_zone
|
||||
|
||||
data = cls.client.create_volume(Size=1, AvailabilityZone=zone)
|
||||
volume_id = data['VolumeId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_volume,
|
||||
VolumeId=volume_id)
|
||||
cls.get_volume_waiter().wait_available(volume_id)
|
||||
|
||||
def _create_snapshot():
|
||||
try:
|
||||
return cls.client.create_snapshot(VolumeId=volume_id)
|
||||
except botocore.exceptions.ClientError as e:
|
||||
code = (e.response.get('ResponseMetadata', {})
|
||||
.get('HTTPStatusCode'))
|
||||
if not code or code != 500:
|
||||
raise
|
||||
|
||||
waiter = base.EC2Waiter(_create_snapshot)
|
||||
cls.ids = list()
|
||||
while len(cls.ids) < cls.SNAPSHOTS_COUNT:
|
||||
time.sleep(10)
|
||||
data = waiter.wait_for_result()
|
||||
snapshot_id = data['SnapshotId']
|
||||
cls.addResourceCleanUpStatic(cls.client.delete_snapshot,
|
||||
SnapshotId=snapshot_id)
|
||||
cls.get_snapshot_waiter().wait_available(snapshot_id,
|
||||
final_set=('completed'))
|
||||
cls.ids.append(snapshot_id)
|
||||
|
||||
@decorators.idempotent_id('f44729b1-42d7-4f18-b5e0-f8dc2a03e624')
|
||||
def test_simple_snapshots_paging_with_many_results(self):
|
||||
data = self.client.describe_snapshots(MaxResults=500,
|
||||
OwnerIds=['self'])
|
||||
self.assertNotEmpty(data['Snapshots'])
|
||||
count = 0
|
||||
for s in data['Snapshots']:
|
||||
if s['SnapshotId'] in self.ids:
|
||||
count += 1
|
||||
self.assertEqual(self.SNAPSHOTS_COUNT, count)
|
||||
|
||||
@decorators.idempotent_id('3146c81d-84c0-4817-9318-328f92bece7f')
|
||||
def test_simple_snapshots_paging_with_min_results(self):
|
||||
data = self.client.describe_snapshots(MaxResults=5, OwnerIds=['self'])
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Snapshots'])
|
||||
|
||||
@decorators.idempotent_id('fef90b60-0a46-4802-a822-98ccb58ff18c')
|
||||
def test_snapshots_paging(self):
|
||||
count = 0
|
||||
max_results = 5
|
||||
kwargs = {'MaxResults': max_results, 'OwnerIds': ['self']}
|
||||
while True:
|
||||
data = self.client.describe_snapshots(*[], **kwargs)
|
||||
self.assertGreaterEqual(max_results, len(data['Snapshots']))
|
||||
for s in data['Snapshots']:
|
||||
if s['SnapshotId'] in self.ids:
|
||||
count += 1
|
||||
if 'NextToken' not in data:
|
||||
break
|
||||
kwargs['NextToken'] = data['NextToken']
|
||||
|
||||
self.assertEqual(self.SNAPSHOTS_COUNT, count)
|
||||
|
||||
@decorators.idempotent_id('8379d875-2979-4573-858f-2fd331ae992c')
|
||||
def test_invalid_paging(self):
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_snapshots, MaxResults=4)
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.describe_snapshots,
|
||||
MaxResults=5, SnapshotIds=[self.ids[0]])
|
||||
|
||||
|
||||
class InstancePagingTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
RESERVATIONS_COUNT = 2
|
||||
INSTANCES_IN_RESERVATIONS_COUNT = 3
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(InstancePagingTest, cls).setUpClass()
|
||||
if 'amazon' in CONF.aws.ec2_url:
|
||||
raise cls.skipException('Paging is broken in Amazon.')
|
||||
if not CONF.aws.image_id:
|
||||
raise cls.skipException('aws image_id does not provided')
|
||||
|
||||
cls.ids = list()
|
||||
cls.reservation_ids = list()
|
||||
kwargs = {
|
||||
'ImageId': CONF.aws.image_id,
|
||||
'InstanceType': CONF.aws.instance_type,
|
||||
'Placement': {'AvailabilityZone': CONF.aws.aws_zone},
|
||||
'MinCount': cls.INSTANCES_IN_RESERVATIONS_COUNT,
|
||||
'MaxCount': cls.INSTANCES_IN_RESERVATIONS_COUNT
|
||||
}
|
||||
for dummy in xrange(0, cls.RESERVATIONS_COUNT):
|
||||
data = cls.client.run_instances(*[], **kwargs)
|
||||
for instance in data['Instances']:
|
||||
cls.ids.append(instance['InstanceId'])
|
||||
cls.reservation_ids.append(data['ReservationId'])
|
||||
|
||||
cls.addResourceCleanUpStatic(cls.client.terminate_instances,
|
||||
InstanceIds=cls.ids)
|
||||
for instance_id in cls.ids:
|
||||
cls.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
|
||||
@decorators.idempotent_id('703da498-c73f-4fd1-a2be-2feddb5292d0')
|
||||
def test_simple_instances_paging_with_many_results(self):
|
||||
data = self.client.describe_instances(MaxResults=500)
|
||||
self.assertNotIn('NextToken', data)
|
||||
self.assertNotEmpty(data['Reservations'])
|
||||
rcount = 0
|
||||
for r in data['Reservations']:
|
||||
if r['ReservationId'] in self.reservation_ids:
|
||||
rcount += 1
|
||||
self.assertEqual(self.RESERVATIONS_COUNT, rcount)
|
||||
count = self.RESERVATIONS_COUNT * self.INSTANCES_IN_RESERVATIONS_COUNT
|
||||
instances = set()
|
||||
self._collect_own_instances(data, instances)
|
||||
self.assertEqual(count, len(instances))
|
||||
|
||||
@decorators.idempotent_id('f494a2a8-6d75-4ef4-ae15-ac4fd1269107')
|
||||
def test_simple_instances_paging_with_min_results(self):
|
||||
max_results = 5
|
||||
data = self.client.describe_instances(MaxResults=max_results)
|
||||
self.assertIn('NextToken', data)
|
||||
self.assertEqual(max_results, self._count_instances(data))
|
||||
|
||||
@decorators.idempotent_id('429802be-d599-4732-a310-3ffe8274df54')
|
||||
def test_instances_paging(self):
|
||||
max_results = 5
|
||||
kwargs = {'MaxResults': max_results}
|
||||
instances = set()
|
||||
while True:
|
||||
data = self.client.describe_instances(*[], **kwargs)
|
||||
self.assertGreaterEqual(max_results, self._count_instances(data))
|
||||
self._collect_own_instances(data, instances)
|
||||
if 'NextToken' not in data:
|
||||
break
|
||||
kwargs['NextToken'] = data['NextToken']
|
||||
|
||||
count = self.RESERVATIONS_COUNT * self.INSTANCES_IN_RESERVATIONS_COUNT
|
||||
self.assertEqual(count, len(instances))
|
||||
|
||||
@decorators.idempotent_id('061d564d-6d3a-44a8-bec9-9dba04f6f362')
|
||||
def test_invalid_paging(self):
|
||||
self.assertRaises('InvalidParameterValue',
|
||||
self.client.describe_instances, MaxResults=4)
|
||||
|
||||
self.assertRaises('InvalidParameterCombination',
|
||||
self.client.describe_instances,
|
||||
MaxResults=5, InstanceIds=[self.ids[0]])
|
||||
|
||||
def _collect_own_instances(self, data, instances):
|
||||
for reservation in data['Reservations']:
|
||||
for instance in reservation['Instances']:
|
||||
if instance['InstanceId'] in self.ids:
|
||||
instances.add(instance['InstanceId'])
|
||||
|
||||
def _count_instances(self, data):
|
||||
count = 0
|
||||
for reservation in data['Reservations']:
|
||||
count += len(reservation['Instances'])
|
||||
return count
|
|
@ -1,157 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import time
|
||||
|
||||
from oslo_log import log
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
from ec2api.tests.functional.scenario import base as scenario_base
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class VpcAddressTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
@base.skip_without_vpc()
|
||||
@decorators.idempotent_id('aa667fc6-fd9e-4664-92b8-23263d643d9e')
|
||||
@testtools.skipUnless(CONF.aws.image_id, "image id is not defined")
|
||||
def test_auto_diassociate_address(self):
|
||||
vpc_id, subnet_id = self.create_vpc_and_subnet('10.3.0.0/20')
|
||||
ni_id1 = self.create_network_interface(subnet_id)
|
||||
gw_id = self.create_and_attach_internet_gateway(vpc_id)
|
||||
self.prepare_route(vpc_id, gw_id)
|
||||
alloc_id1, public_ip1 = self.allocate_address(True)
|
||||
alloc_id2, _ = self.allocate_address(True)
|
||||
|
||||
data = self.client.create_network_interface(SubnetId=subnet_id)
|
||||
ni_id2 = data['NetworkInterface']['NetworkInterfaceId']
|
||||
clean_ni2 = self.addResourceCleanUp(
|
||||
self.client.delete_network_interface, NetworkInterfaceId=ni_id2)
|
||||
self.get_network_interface_waiter().wait_available(ni_id2)
|
||||
|
||||
kwargs = {
|
||||
'ImageId': CONF.aws.image_id,
|
||||
'InstanceType': CONF.aws.instance_type,
|
||||
'MinCount': 1,
|
||||
'MaxCount': 1,
|
||||
'NetworkInterfaces': [
|
||||
{'NetworkInterfaceId': ni_id1, 'DeviceIndex': 0}]
|
||||
}
|
||||
data = self.client.run_instances(*[], **kwargs)
|
||||
instance_id = data['Instances'][0]['InstanceId']
|
||||
clean_i = self.addResourceCleanUp(self.client.terminate_instances,
|
||||
InstanceIds=[instance_id])
|
||||
self.get_instance_waiter().wait_available(instance_id,
|
||||
final_set=('running'))
|
||||
data = self.client.attach_network_interface(DeviceIndex=1,
|
||||
InstanceId=instance_id, NetworkInterfaceId=ni_id2)
|
||||
attachment_id = data['AttachmentId']
|
||||
|
||||
# There are multiple interfaces attached to instance 'i-5310c5af'.
|
||||
# Please specify an interface ID for the operation instead.
|
||||
self.assertRaises('InvalidInstanceID',
|
||||
self.client.associate_address,
|
||||
InstanceId=instance_id, AllocationId=alloc_id1)
|
||||
|
||||
# The networkInterface ID 'eni-ffffffff' does not exist
|
||||
self.assertRaises('InvalidNetworkInterfaceID.NotFound',
|
||||
self.client.associate_address,
|
||||
AllocationId=alloc_id1, NetworkInterfaceId='eni-ffffffff')
|
||||
|
||||
# NOTE(andrey-mp): Amazon needs only network interface if several
|
||||
# present in instance. Error will be there if instance is passed.
|
||||
data = self.client.associate_address(
|
||||
AllocationId=alloc_id1, NetworkInterfaceId=ni_id1)
|
||||
assoc_id1 = data['AssociationId']
|
||||
clean_aa1 = self.addResourceCleanUp(self.client.disassociate_address,
|
||||
AssociationId=assoc_id1)
|
||||
self.get_address_assoc_waiter().wait_available(
|
||||
{'AllocationId': alloc_id1})
|
||||
|
||||
instance = self.get_instance(instance_id)
|
||||
nis = instance.get('NetworkInterfaces', [])
|
||||
self.assertEqual(2, len(nis))
|
||||
for ni in nis:
|
||||
if ni['NetworkInterfaceId'] == ni_id1:
|
||||
self.assertIsNotNone(ni.get('Association'))
|
||||
self.assertEqual(public_ip1, ni['Association']['PublicIp'])
|
||||
elif ni['NetworkInterfaceId'] == ni_id2:
|
||||
self.assertIsNone(ni.get('Association'))
|
||||
else:
|
||||
self.assertTrue(False, 'Unknown interface found: ' + str(ni))
|
||||
|
||||
data = self.client.describe_network_interfaces(
|
||||
NetworkInterfaceIds=[ni_id1, ni_id2])
|
||||
self.assertEqual(2, len(data['NetworkInterfaces']))
|
||||
self.assertEqual('in-use', data['NetworkInterfaces'][0]['Status'])
|
||||
self.assertEqual('in-use', data['NetworkInterfaces'][1]['Status'])
|
||||
|
||||
# NOTE(andrery-mp): associate second address and set delete on
|
||||
# termination to True for interface
|
||||
data = self.client.associate_address(
|
||||
AllocationId=alloc_id2, NetworkInterfaceId=ni_id2)
|
||||
assoc_id2 = data['AssociationId']
|
||||
clean_aa2 = self.addResourceCleanUp(self.client.disassociate_address,
|
||||
AssociationId=assoc_id2)
|
||||
self.get_address_assoc_waiter().wait_available(
|
||||
{'AllocationId': alloc_id2})
|
||||
|
||||
kwargs = {
|
||||
'NetworkInterfaceId': ni_id2,
|
||||
'Attachment': {
|
||||
'AttachmentId': attachment_id,
|
||||
'DeleteOnTermination': True,
|
||||
}
|
||||
}
|
||||
self.client.modify_network_interface_attribute(*[], **kwargs)
|
||||
|
||||
# NOTE(andrey-mp): cleanup
|
||||
time.sleep(3)
|
||||
|
||||
self.client.terminate_instances(InstanceIds=[instance_id])
|
||||
self.cancelResourceCleanUp(clean_i)
|
||||
self.get_instance_waiter().wait_delete(instance_id)
|
||||
|
||||
self.assertRaises('InvalidNetworkInterfaceID.NotFound',
|
||||
self.client.describe_network_interfaces,
|
||||
NetworkInterfaceIds=[ni_id2])
|
||||
self.cancelResourceCleanUp(clean_ni2)
|
||||
self.cancelResourceCleanUp(clean_aa2)
|
||||
|
||||
data = self.client.describe_network_interfaces(
|
||||
NetworkInterfaceIds=[ni_id1])
|
||||
self.assertEqual(1, len(data['NetworkInterfaces']))
|
||||
self.assertEqual('available', data['NetworkInterfaces'][0]['Status'])
|
||||
ni = data['NetworkInterfaces'][0]
|
||||
self.assertIsNotNone(ni.get('Association'))
|
||||
self.assertEqual(public_ip1, ni['Association']['PublicIp'])
|
||||
|
||||
data = self.client.describe_addresses(AllocationIds=[alloc_id1,
|
||||
alloc_id2])
|
||||
for address in data['Addresses']:
|
||||
if address['AllocationId'] == alloc_id1:
|
||||
self.assertIsNotNone(address.get('AssociationId'))
|
||||
elif address['AllocationId'] == alloc_id2:
|
||||
self.assertIsNone(address.get('AssociationId'))
|
||||
|
||||
self.client.disassociate_address(AssociationId=assoc_id1)
|
||||
self.cancelResourceCleanUp(clean_aa1)
|
||||
self.get_address_assoc_waiter().wait_delete(
|
||||
{'AllocationId': alloc_id1})
|
|
@ -1,278 +0,0 @@
|
|||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import urllib2
|
||||
|
||||
from lxml import etree
|
||||
from oslo_log import log
|
||||
import paramiko
|
||||
from tempest.lib.common import ssh
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
import testtools
|
||||
|
||||
from ec2api.tests.functional import base
|
||||
from ec2api.tests.functional import config
|
||||
from ec2api.tests.functional.scenario import base as scenario_base
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class VpnTest(scenario_base.BaseScenarioTest):
|
||||
|
||||
CUSTOMER_GATEWAY_IP = '198.51.100.77'
|
||||
CUSTOMER_VPN_CIDR = '172.16.25.0/24'
|
||||
OPENSWAN_LINK = ('http://mirrors.kernel.org/ubuntu/pool/universe/o/'
|
||||
'openswan/openswan_2.6.38-1_i386.deb')
|
||||
|
||||
@classmethod
|
||||
@base.safe_setup
|
||||
def setUpClass(cls):
|
||||
super(VpnTest, cls).setUpClass()
|
||||
if not base.TesterStateHolder().get_vpc_enabled():
|
||||
raise cls.skipException('VPC is disabled')
|
||||
base.check_network_feature_enabled('vpnaas')
|
||||
|
||||
@decorators.idempotent_id('63c2ac38-cfee-45d3-b765-c9b43859660d')
|
||||
def test_vpn_routing(self):
|
||||
vpc_id, _subnet_id = self.create_vpc_and_subnet('10.42.0.0/20')
|
||||
|
||||
vpn_data = self._create_and_configure_vpn(
|
||||
vpc_id, self.CUSTOMER_GATEWAY_IP, self.CUSTOMER_VPN_CIDR)
|
||||
vgw_id = vpn_data['VpnGatewayId']
|
||||
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])
|
||||
rtb_id = data['RouteTables'][0]['RouteTableId']
|
||||
data = self.client.describe_route_tables(RouteTableIds=[rtb_id])
|
||||
data = data['RouteTables'][0]
|
||||
route = next((r for r in data['Routes']
|
||||
if r['DestinationCidrBlock'] == self.CUSTOMER_VPN_CIDR),
|
||||
None)
|
||||
if route:
|
||||
self.assertEqual('active', route['State'])
|
||||
self.assertEqual('EnableVgwRoutePropagation', route['Origin'])
|
||||
self.assertIn('PropagatingVgws', data)
|
||||
self.assertNotEmpty(data['PropagatingVgws'])
|
||||
self.assertEqual(vgw_id, data['PropagatingVgws'][0]['GatewayId'])
|
||||
|
||||
@decorators.idempotent_id('9e284d9e-8fee-43c7-bcfb-8ed0dfa27dbc')
|
||||
@testtools.skipUnless(CONF.aws.run_ssh, 'SSH tests are disabled.')
|
||||
@testtools.skipUnless(CONF.aws.run_long_tests, 'Slow test has skipped.')
|
||||
@testtools.skipUnless(CONF.aws.image_id_ubuntu,
|
||||
"ubuntu image id is not defined")
|
||||
@testtools.skipUnless(CONF.aws.image_id,
|
||||
"image id is not defined")
|
||||
def test_vpn_connectivity(self):
|
||||
is_amazon = 'amazon' in CONF.aws.ec2_url
|
||||
|
||||
response = urllib2.urlopen(self.OPENSWAN_LINK, timeout=30)
|
||||
content = response.read()
|
||||
if not is_amazon:
|
||||
# NOTE(andrey-mp): gating in openstack doesn't have internet access
|
||||
# so we need to download this package and install it with dpkg
|
||||
filename = os.path.basename(self.OPENSWAN_LINK)
|
||||
f = open(filename, 'w')
|
||||
f.write(content)
|
||||
f.close()
|
||||
|
||||
key_name = data_utils.rand_name('testkey')
|
||||
pkey = self.create_key_pair(key_name)
|
||||
|
||||
# run ubuntu instance to create one of VPN endpoint inside
|
||||
sec_group_name = self.create_standard_security_group()
|
||||
instance_id_ubuntu = self.run_instance(
|
||||
KeyName=key_name, ImageId=CONF.aws.image_id_ubuntu,
|
||||
SecurityGroups=[sec_group_name])
|
||||
public_ip_ubuntu = self.get_instance_ip(instance_id_ubuntu)
|
||||
instance = self.get_instance(instance_id_ubuntu)
|
||||
private_ip_ubuntu = instance['PrivateIpAddress']
|
||||
|
||||
# create VPC, ..., VPN
|
||||
vpc_id, subnet_id = self.create_vpc_and_subnet('10.43.0.0/20')
|
||||
self.prepare_vpc_default_security_group(vpc_id)
|
||||
vpn_data = self._create_and_configure_vpn(
|
||||
vpc_id, public_ip_ubuntu, private_ip_ubuntu + '/32')
|
||||
|
||||
# run general instance inside VPC
|
||||
instance_id = self.run_instance(KeyName=key_name,
|
||||
ImageId=CONF.aws.image_id,
|
||||
SubnetId=subnet_id)
|
||||
instance = self.get_instance(instance_id)
|
||||
private_ip_in_vpc = instance['PrivateIpAddress']
|
||||
|
||||
# configure ubuntu, install openswan and run it
|
||||
ssh_client = ssh.Client(public_ip_ubuntu, CONF.aws.image_user_ubuntu,
|
||||
pkey=pkey)
|
||||
if not is_amazon:
|
||||
self._upload_file(ssh_client, filename, filename)
|
||||
ssh_client.exec_command('sudo DEBIAN_FRONTEND=noninteractive'
|
||||
' dpkg -i ' + filename)
|
||||
else:
|
||||
ssh_client.exec_command('DEBIAN_FRONTEND=noninteractive sudo '
|
||||
'apt-get install -fqy openswan')
|
||||
ssh_client.exec_command('sudo -s su -c "'
|
||||
'echo 1 > /proc/sys/net/ipv4/ip_forward"')
|
||||
ssh_client.exec_command(
|
||||
'for vpn in /proc/sys/net/ipv4/conf/*; do sudo -s su -c'
|
||||
' "echo 0 > $vpn/accept_redirects; echo 0 > $vpn/send_redirects";'
|
||||
' done')
|
||||
sysctl_additions = [
|
||||
'net.ipv4.ip_forward = 1',
|
||||
'net.ipv4.conf.all.accept_redirects = 0',
|
||||
'net.ipv4.conf.all.send_redirects = 0']
|
||||
for item in sysctl_additions:
|
||||
ssh_client.exec_command(
|
||||
'sudo -s su -c "echo \'' + item + '\' >> /etc/sysctl.conf"')
|
||||
ssh_client.exec_command('sudo sysctl -p')
|
||||
ipsec_conf, ipsec_secrets = self._get_ipsec_conf(
|
||||
vpn_data['VpnConnectionId'], private_ip_ubuntu)
|
||||
ssh_client.exec_command('sudo -s su -c "echo \'\' > /etc/ipsec.conf"')
|
||||
for fstr in ipsec_conf:
|
||||
ssh_client.exec_command(
|
||||
'sudo -s su -c "echo \'%s\' >> /etc/ipsec.conf"' % fstr)
|
||||
ssh_client.exec_command(
|
||||
'sudo -s su -c "echo \'%s\' > /etc/ipsec.secrets"' % ipsec_secrets)
|
||||
|
||||
ssh_client.exec_command('sudo service ipsec restart')
|
||||
|
||||
try:
|
||||
self.get_vpn_connection_tunnel_waiter().wait_available(
|
||||
vpn_data['VpnConnectionId'], ('UP'))
|
||||
except Exception:
|
||||
exc_info = sys.exc_info()
|
||||
try:
|
||||
output = ssh_client.exec_command('sudo ipsec auto --status')
|
||||
LOG.warning(output)
|
||||
except Exception:
|
||||
pass
|
||||
raise exc_info[1], None, exc_info[2]
|
||||
time.sleep(10)
|
||||
|
||||
ssh_client.exec_command('ping -c 4 %s' % private_ip_in_vpc)
|
||||
|
||||
def _upload_file(self, ssh_client, local_path, remote_path):
|
||||
ssh = ssh_client._get_ssh_connection()
|
||||
transport = ssh.get_transport()
|
||||
sftp_client = paramiko.SFTPClient.from_transport(transport)
|
||||
sftp_client.put(local_path, remote_path)
|
||||
|
||||
def _create_and_configure_vpn(self, vpc_id, cgw_ip, customer_subnet):
|
||||
data = self.client.create_customer_gateway(
|
||||
Type='ipsec.1', PublicIp=cgw_ip, BgpAsn=65000)
|
||||
cgw_id = data['CustomerGateway']['CustomerGatewayId']
|
||||
self.addResourceCleanUp(
|
||||
self.client.delete_customer_gateway, CustomerGatewayId=cgw_id)
|
||||
self.get_customer_gateway_waiter().wait_available(cgw_id)
|
||||
|
||||
data = self.client.create_vpn_gateway(
|
||||
Type='ipsec.1', AvailabilityZone=CONF.aws.aws_zone)
|
||||
vgw_id = data['VpnGateway']['VpnGatewayId']
|
||||
self.addResourceCleanUp(
|
||||
self.client.delete_vpn_gateway, VpnGatewayId=vgw_id)
|
||||
self.get_vpn_gateway_waiter().wait_available(vgw_id)
|
||||
|
||||
data = self.client.attach_vpn_gateway(VpnGatewayId=vgw_id,
|
||||
VpcId=vpc_id)
|
||||
self.addResourceCleanUp(self.client.detach_vpn_gateway,
|
||||
VpnGatewayId=vgw_id, VpcId=vpc_id)
|
||||
self.get_vpn_gateway_attachment_waiter().wait_available(
|
||||
vgw_id, 'attached')
|
||||
|
||||
data = self.client.describe_route_tables(
|
||||
Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}])
|
||||
rtb_id = data['RouteTables'][0]['RouteTableId']
|
||||
data = self.client.enable_vgw_route_propagation(RouteTableId=rtb_id,
|
||||
GatewayId=vgw_id)
|
||||
self.addResourceCleanUp(self.client.disable_vgw_route_propagation,
|
||||
RouteTableId=rtb_id, GatewayId=vgw_id)
|
||||
|
||||
data = self.client.create_vpn_connection(
|
||||
CustomerGatewayId=cgw_id, VpnGatewayId=vgw_id,
|
||||
Options={'StaticRoutesOnly': True}, Type='ipsec.1')
|
||||
vpn_data = data['VpnConnection']
|
||||
vpn_id = data['VpnConnection']['VpnConnectionId']
|
||||
self.addResourceCleanUp(self.client.delete_vpn_connection,
|
||||
VpnConnectionId=vpn_id)
|
||||
self.get_vpn_connection_waiter().wait_available(vpn_id)
|
||||
|
||||
data = self.client.create_vpn_connection_route(
|
||||
VpnConnectionId=vpn_id,
|
||||
DestinationCidrBlock=customer_subnet)
|
||||
self.get_vpn_connection_route_waiter(customer_subnet).wait_available(
|
||||
vpn_id)
|
||||
|
||||
return vpn_data
|
||||
|
||||
def _get_ipsec_conf(self, vpn_connection_id, private_ip_ubuntu):
|
||||
data = self.client.describe_vpn_connections(
|
||||
VpnConnectionIds=[vpn_connection_id])
|
||||
vpn_data = data['VpnConnections'][0]
|
||||
vpn_config = etree.fromstring(
|
||||
vpn_data['CustomerGatewayConfiguration'])
|
||||
psks = vpn_config.xpath(
|
||||
'/vpn_connection/ipsec_tunnel/ike/pre_shared_key')
|
||||
self.assertNotEmpty(psks)
|
||||
vgw_ip = vpn_config.xpath(
|
||||
'/vpn_connection/ipsec_tunnel/vpn_gateway/tunnel_outside_address'
|
||||
'/ip_address')
|
||||
self.assertTrue(vgw_ip)
|
||||
|
||||
ipsec_key = psks[0].text
|
||||
vgw_ip = vgw_ip[0].text
|
||||
|
||||
ipsec_conf = []
|
||||
for item in self._ipsec_conf:
|
||||
ipsec_conf.append(item % {
|
||||
'vpc_cidr': '10.43.0.0/20',
|
||||
'vgw_ip': vgw_ip,
|
||||
'private_ip_ubuntu': private_ip_ubuntu})
|
||||
|
||||
ipsec_secrets = ('%(private_ip_ubuntu)s %(vgw_ip)s: '
|
||||
'PSK \\"%(ipsec_key)s\\"' % {
|
||||
'private_ip_ubuntu': private_ip_ubuntu,
|
||||
'vgw_ip': vgw_ip,
|
||||
'ipsec_key': ipsec_key})
|
||||
|
||||
return ipsec_conf, ipsec_secrets
|
||||
|
||||
_ipsec_conf = [
|
||||
'## general configuration parameters ##',
|
||||
'config setup',
|
||||
' plutodebug=all',
|
||||
' plutostderrlog=/var/log/pluto.log',
|
||||
' protostack=netkey',
|
||||
' nat_traversal=yes',
|
||||
' virtual_private=%%v4:%(vpc_cidr)s',
|
||||
' nhelpers=0',
|
||||
'## connection definition in Debian ##',
|
||||
'conn my-conn',
|
||||
' authby=secret',
|
||||
' auto=start',
|
||||
' pfs=yes',
|
||||
' type=tunnel',
|
||||
' #left side (myside)',
|
||||
' left=%(private_ip_ubuntu)s',
|
||||
' leftsubnet=%(private_ip_ubuntu)s/32',
|
||||
' leftnexthop=%(vgw_ip)s',
|
||||
' leftsourceip=%(private_ip_ubuntu)s',
|
||||
' #right security gateway (VPN side)',
|
||||
' right=%(vgw_ip)s',
|
||||
' rightsubnet=%(vpc_cidr)s',
|
||||
' rightnexthop=%(private_ip_ubuntu)s']
|
|
@ -20,7 +20,7 @@ from rally.common import utils as rutils
|
|||
from rally import consts
|
||||
from rally.task import context
|
||||
|
||||
from ec2api.tests.functional import botocoreclient
|
||||
from ec2api.tests import botocoreclient
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -19,7 +19,7 @@ from rally import consts
|
|||
from rally import osclients
|
||||
from rally.task import context
|
||||
|
||||
from ec2api.tests.functional import botocoreclient
|
||||
from ec2api.tests import botocoreclient
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -15,7 +15,8 @@ from rally import osclients
|
|||
from rally.plugins.openstack import scenario
|
||||
from rally.task import atomic
|
||||
|
||||
from ec2api.tests.functional import botocoreclient
|
||||
from ec2api.tests import botocoreclient
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -38,9 +38,6 @@ console_scripts =
|
|||
ec2-api-metadata=ec2api.cmd.api_metadata:main
|
||||
ec2-api-s3=ec2api.cmd.api_s3:main
|
||||
|
||||
tempest.test_plugins =
|
||||
aws_tests = ec2api.tests.functional.plugin:AWSTempestPlugin
|
||||
|
||||
[build_sphinx]
|
||||
all_files = 1
|
||||
build-dir = doc/build
|
||||
|
|
2
tox.ini
2
tox.ini
|
@ -64,7 +64,7 @@ ignore = E121,E122,E123,E124,E126,E127,E128,E711,E712,H102,H303,H404,F403,F811,F
|
|||
# H106: Don’t put vim configuration in source files
|
||||
# H203: Use assertIs(Not)None to check for None
|
||||
enable-extensions=H106,H203
|
||||
exclude = .venv,.git,.tox,dist,envname,*lib/python*,*egg,build,tools,ec2api/tests/functional/obsolete
|
||||
exclude = .venv,.git,.tox,dist,envname,*lib/python*,*egg,build,tools
|
||||
max-complexity=25
|
||||
|
||||
[hacking]
|
||||
|
|
Loading…
Reference in New Issue