158 lines
6.8 KiB
Python
158 lines
6.8 KiB
Python
# 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})
|