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 import consts
|
||||||
from rally.task import context
|
from rally.task import context
|
||||||
|
|
||||||
from ec2api.tests.functional import botocoreclient
|
from ec2api.tests import botocoreclient
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
|
@ -19,7 +19,7 @@ from rally import consts
|
||||||
from rally import osclients
|
from rally import osclients
|
||||||
from rally.task import context
|
from rally.task import context
|
||||||
|
|
||||||
from ec2api.tests.functional import botocoreclient
|
from ec2api.tests import botocoreclient
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
|
@ -15,7 +15,8 @@ from rally import osclients
|
||||||
from rally.plugins.openstack import scenario
|
from rally.plugins.openstack import scenario
|
||||||
from rally.task import atomic
|
from rally.task import atomic
|
||||||
|
|
||||||
from ec2api.tests.functional import botocoreclient
|
from ec2api.tests import botocoreclient
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,6 @@ console_scripts =
|
||||||
ec2-api-metadata=ec2api.cmd.api_metadata:main
|
ec2-api-metadata=ec2api.cmd.api_metadata:main
|
||||||
ec2-api-s3=ec2api.cmd.api_s3:main
|
ec2-api-s3=ec2api.cmd.api_s3:main
|
||||||
|
|
||||||
tempest.test_plugins =
|
|
||||||
aws_tests = ec2api.tests.functional.plugin:AWSTempestPlugin
|
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
all_files = 1
|
all_files = 1
|
||||||
build-dir = doc/build
|
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
|
# H106: Don’t put vim configuration in source files
|
||||||
# H203: Use assertIs(Not)None to check for None
|
# H203: Use assertIs(Not)None to check for None
|
||||||
enable-extensions=H106,H203
|
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
|
max-complexity=25
|
||||||
|
|
||||||
[hacking]
|
[hacking]
|
||||||
|
|
Loading…
Reference in New Issue