# 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 tempest_lib.openstack.common import log 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 CONF.aws.vpc_enabled: raise cls.skipException('VPC is disabled') resp, data = cls.client.CreateVpc(CidrBlock=cls.VPC_CIDR) if resp.status_code != 200: LOG.error(base.EC2ErrorConverter(data)) assert 200 == resp.status_code cls.vpc_id = data['Vpc']['VpcId'] cls.addResourceCleanUpStatic(cls.client.DeleteVpc, VpcId=cls.vpc_id) cls.get_vpc_waiter().wait_available(cls.vpc_id) aws_zone = CONF.aws.aws_zone resp, data = cls.client.CreateSubnet(VpcId=cls.vpc_id, CidrBlock=cls.SUBNET_CIDR, AvailabilityZone=aws_zone) if resp.status_code != 200: LOG.error(base.EC2ErrorConverter(data)) assert 200 == resp.status_code cls.subnet_id = data['Subnet']['SubnetId'] cls.addResourceCleanUpStatic(cls.client.DeleteSubnet, SubnetId=cls.subnet_id) cls.get_subnet_waiter().wait_available(cls.subnet_id) def _wait_assignment(self, ni_id, resp, data): # NOTE(andrey-mp): Amazon don't do it quickly and there is no way # to wait this request time.sleep(5) def test_delete_subnet_with_network_interface(self): resp, data = self.client.CreateSubnet(VpcId=self.vpc_id, CidrBlock='10.7.1.0/28') self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) subnet_id = data['Subnet']['SubnetId'] res_clean_subnet = self.addResourceCleanUp(self.client.DeleteSubnet, SubnetId=subnet_id) self.get_subnet_waiter().wait_available(subnet_id) kwargs = { 'SubnetId': subnet_id, 'Description': base.rand_name('ni') } resp, data = self.client.CreateNetworkInterface(*[], **kwargs) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) ni_id = data['NetworkInterface']['NetworkInterfaceId'] res_clean_ni = self.addResourceCleanUp( self.client.DeleteNetworkInterface, NetworkInterfaceId=ni_id) self.get_network_interface_waiter().wait_available(ni_id) resp, data = self.client.DeleteSubnet(SubnetId=subnet_id) self.assertEqual(400, resp.status_code, base.EC2ErrorConverter(data)) self.assertEqual('DependencyViolation', data['Error']['Code']) resp, data = self.client.DeleteNetworkInterface( NetworkInterfaceId=ni_id) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self.cancelResourceCleanUp(res_clean_ni) self.get_network_interface_waiter().wait_delete(ni_id) resp, data = self.client.DeleteSubnet(SubnetId=subnet_id) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self.cancelResourceCleanUp(res_clean_subnet) self.get_subnet_waiter().wait_delete(subnet_id) def test_create_network_interface(self): kwargs = { 'SubnetId': self.subnet_id, 'Description': base.rand_name('ni') } resp, data = self.client.CreateNetworkInterface(*[], **kwargs) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) ni_id = data['NetworkInterface']['NetworkInterfaceId'] res_clean = self.addResourceCleanUp(self.client.DeleteNetworkInterface, NetworkInterfaceId=ni_id) ni = data['NetworkInterface'] self.assertEqual(self.vpc_id, ni['VpcId']) self.assertEqual(self.subnet_id, ni['SubnetId']) self.assertEqual(kwargs['Description'], 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) resp, data = self.client.DeleteNetworkInterface( NetworkInterfaceId=ni_id) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self.cancelResourceCleanUp(res_clean) self.get_network_interface_waiter().wait_delete(ni_id) resp, data = self.client.DescribeNetworkInterfaces( NetworkInterfaceIds=[ni_id]) self.assertEqual(400, resp.status_code) self.assertEqual('InvalidNetworkInterfaceID.NotFound', data['Error']['Code']) # TODO(andrey-mp): add creation with addresses 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) resp, data = self.client.DescribeSubnets(SubnetIds=[self.subnet_id]) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) count_before = data['Subnets'][0]['AvailableIpAddressCount'] kwargs = { 'SubnetId': self.subnet_id, } addresses = [] while True: resp, data = self.client.CreateNetworkInterface(*[], **kwargs) if resp.status_code != 200: break ni_id = data['NetworkInterface']['NetworkInterfaceId'] res_clean = self.addResourceCleanUp( self.client.DeleteNetworkInterface, NetworkInterfaceId=ni_id) addresses.append((ni_id, res_clean)) self.assertEqual(400, resp.status_code) self.assertEqual('NetworkInterfaceLimitExceeded', data['Error']['Code']) resp, data = self.client.DescribeSubnets(SubnetIds=[self.subnet_id]) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) 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: kwargs = { 'NetworkInterfaceId': addr[0], } resp, data = self.client.DeleteNetworkInterface(*[], **kwargs) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self.cancelResourceCleanUp(addr[1]) self.get_network_interface_waiter().wait_delete(addr[0]) def test_unassign_primary_addresses(self): kwargs = { 'SubnetId': self.subnet_id, } resp, data = self.client.CreateNetworkInterface(*[], **kwargs) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) ni_id = data['NetworkInterface']['NetworkInterfaceId'] res_clean = self.addResourceCleanUp(self.client.DeleteNetworkInterface, NetworkInterfaceId=ni_id) primary_address = data['NetworkInterface'].get('PrivateIpAddress') self.get_network_interface_waiter().wait_available(ni_id) resp, data = self.client.UnassignPrivateIpAddresses( NetworkInterfaceId=ni_id, PrivateIpAddresses=[primary_address]) self.assertEqual(400, resp.status_code) self.assertEqual('InvalidParameterValue', data['Error']['Code']) resp, data = self.client.DeleteNetworkInterface( NetworkInterfaceId=ni_id) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self.cancelResourceCleanUp(res_clean) self.get_network_interface_waiter().wait_delete(ni_id) def test_assign_unassign_private_addresses_by_count(self): resp, data = self.client.DescribeSubnets(SubnetIds=[self.subnet_id]) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) count = data['Subnets'][0]['AvailableIpAddressCount'] kwargs = { 'SubnetId': self.subnet_id, } resp, data = self.client.CreateNetworkInterface(*[], **kwargs) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) ni_id = data['NetworkInterface']['NetworkInterfaceId'] res_clean = self.addResourceCleanUp(self.client.DeleteNetworkInterface, NetworkInterfaceId=ni_id) self.get_network_interface_waiter().wait_available(ni_id) resp, data = self.client.AssignPrivateIpAddresses( NetworkInterfaceId=ni_id, SecondaryPrivateIpAddressCount=2) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self._wait_assignment(ni_id, resp, data) resp, data = self.client.DescribeSubnets(SubnetIds=[self.subnet_id]) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) count_after = data['Subnets'][0]['AvailableIpAddressCount'] self.assertEqual(count - 3, count_after) resp, data = self.client.DescribeNetworkInterfaces( NetworkInterfaceIds=[ni_id]) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) addresses = [] for addr in data['NetworkInterfaces'][0]['PrivateIpAddresses']: if not addr['Primary']: addresses.append(addr['PrivateIpAddress']) self.assertEqual(2, len(addresses)) resp, data = self.client.UnassignPrivateIpAddresses( NetworkInterfaceId=ni_id, PrivateIpAddresses=addresses) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self._wait_assignment(ni_id, resp, data) resp, data = self.client.DescribeSubnets(SubnetIds=[self.subnet_id]) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) count_after = data['Subnets'][0]['AvailableIpAddressCount'] self.assertEqual(count - 1, count_after) resp, data = self.client.DeleteNetworkInterface( NetworkInterfaceId=ni_id) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self.cancelResourceCleanUp(res_clean) self.get_network_interface_waiter().wait_delete(ni_id) def test_assign_unassign_private_addresses_by_addresses(self): resp, data = self.client.DescribeSubnets(SubnetIds=[self.subnet_id]) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) count = data['Subnets'][0]['AvailableIpAddressCount'] kwargs = { 'SubnetId': self.subnet_id, } resp, data = self.client.CreateNetworkInterface(*[], **kwargs) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) ni_id = data['NetworkInterface']['NetworkInterfaceId'] res_clean = self.addResourceCleanUp(self.client.DeleteNetworkInterface, NetworkInterfaceId=ni_id) self.get_network_interface_waiter().wait_available(ni_id) addresses = ['10.7.0.10', '10.7.0.11'] resp, data = self.client.AssignPrivateIpAddresses( NetworkInterfaceId=ni_id, PrivateIpAddresses=addresses) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self._wait_assignment(ni_id, resp, data) resp, data = self.client.DescribeSubnets(SubnetIds=[self.subnet_id]) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) count_after = data['Subnets'][0]['AvailableIpAddressCount'] # NOTE(Alex): Amazon misses 1 IP address by some reason. self.assertIn(count_after, [count - 3, count - 4]) resp, data = self.client.DescribeNetworkInterfaces( NetworkInterfaceIds=[ni_id]) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) 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)) resp, data = self.client.UnassignPrivateIpAddresses( NetworkInterfaceId=ni_id, PrivateIpAddresses=addresses) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self._wait_assignment(ni_id, resp, data) resp, data = self.client.DescribeSubnets(SubnetIds=[self.subnet_id]) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) count_after = data['Subnets'][0]['AvailableIpAddressCount'] self.assertIn(count_after, [count - 1, count - 2]) resp, data = self.client.DeleteNetworkInterface( NetworkInterfaceId=ni_id) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self.cancelResourceCleanUp(res_clean) self.get_network_interface_waiter().wait_delete(ni_id) def test_network_interface_attribute(self): desc = base.rand_name('ni') kwargs = { 'SubnetId': self.subnet_id, 'Description': desc } resp, data = self.client.CreateNetworkInterface(*[], **kwargs) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) ni_id = data['NetworkInterface']['NetworkInterfaceId'] res_clean = self.addResourceCleanUp(self.client.DeleteNetworkInterface, NetworkInterfaceId=ni_id) self.get_network_interface_waiter().wait_available(ni_id) resp, data = self.client.DescribeNetworkInterfaceAttribute( NetworkInterfaceId=ni_id, attribute='description') self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self.assertEqual(desc, data['Description']['Value']) new_desc = base.rand_name('new-ni') kwargs = { 'NetworkInterfaceId': ni_id, 'Description': {'Value': new_desc} } resp, data = self.client.ModifyNetworkInterfaceAttribute(*[], **kwargs) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) resp, data = self.client.DescribeNetworkInterfaceAttribute( NetworkInterfaceId=ni_id, attribute='description') self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self.assertEqual(new_desc, data['Description']['Value']) kwargs = { 'NetworkInterfaceId': ni_id, 'SourceDestCheck': {'Value': False} } resp, data = self.client.ModifyNetworkInterfaceAttribute(*[], **kwargs) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) resp, data = self.client.DescribeNetworkInterfaceAttribute( NetworkInterfaceId=ni_id, attribute='sourceDestCheck') self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self.assertEqual(False, data['SourceDestCheck']['Value']) # NOTE(andrey-mp): ResetNetworkInterfaceAttribute has inadequate json # scheme in botocore. kwargs = { 'NetworkInterfaceId': ni_id, 'SourceDestCheck': {'Value': True} } resp, data = self.client.ModifyNetworkInterfaceAttribute(*[], **kwargs) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) resp, data = self.client.DescribeNetworkInterfaceAttribute( NetworkInterfaceId=ni_id, attribute='sourceDestCheck') self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self.assertEqual(True, data['SourceDestCheck']['Value']) resp, data = self.client.DeleteNetworkInterface( NetworkInterfaceId=ni_id) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) self.cancelResourceCleanUp(res_clean) self.get_network_interface_waiter().wait_delete(ni_id) def test_attach_network_interface(self): instance_type = CONF.aws.instance_type image_id = CONF.aws.image_id if not image_id: raise self.skipException('aws image_id does not provided') kwargs = { 'SubnetId': self.subnet_id, } resp, data = self.client.CreateNetworkInterface(*[], **kwargs) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) ni_id = data['NetworkInterface']['NetworkInterfaceId'] self.addResourceCleanUp(self.client.DeleteNetworkInterface, NetworkInterfaceId=ni_id) ni = data['NetworkInterface'] address = ni.get('PrivateIpAddress') self.assertIsNotNone(address) self.get_network_interface_waiter().wait_available(ni_id) resp, data = self.client.RunInstances( ImageId=image_id, InstanceType=instance_type, MinCount=1, MaxCount=1, SubnetId=self.subnet_id) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) instance_id = data['Instances'][0]['InstanceId'] self.addResourceCleanUp(self.client.TerminateInstances, InstanceIds=[instance_id]) self.get_instance_waiter().wait_available(instance_id, final_set=('running')) if CONF.aws.run_incompatible_tests: # NOTE(andrey-mp): Amazon can't attach to device index = 0 kwargs = { 'DeviceIndex': 0, 'InstanceId': instance_id, 'NetworkInterfaceId': ni_id } resp, data = self.client.AttachNetworkInterface(*[], **kwargs) self.assertEqual(400, resp.status_code) self.assertEqual('InvalidParameterValue', data['Error']['Code']) kwargs = { 'DeviceIndex': 2, 'InstanceId': instance_id, 'NetworkInterfaceId': ni_id } resp, data = self.client.AttachNetworkInterface(*[], **kwargs) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) attachment_id = data['AttachmentId'] resp, data = self.client.DescribeInstances(InstanceIds=[instance_id]) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data)) reservations = data.get('Reservations', []) self.assertNotEmpty(reservations) instances = reservations[0].get('Instances', []) self.assertNotEmpty(instances) instance = instances[0] nis = instance.get('NetworkInterfaces', []) self.assertEqual(2, len(nis)) ids = [nis[0]['Attachment']['AttachmentId'], nis[1]['Attachment']['AttachmentId']] self.assertIn(attachment_id, ids) resp, data = self.client.DeleteNetworkInterface( NetworkInterfaceId=ni_id) self.assertEqual(400, resp.status_code) self.assertEqual('InvalidParameterValue', data['Error']['Code']) kwargs = { 'AttachmentId': attachment_id, } resp, data = self.client.DetachNetworkInterface(*[], **kwargs) self.assertEqual(200, resp.status_code, base.EC2ErrorConverter(data))