Example #1
0
    def disassociate_address(self, context, public_ip=None,
                             association_id=None):
        LOG.info('Disassociating %s', association_id)
        neutron = clients.neutron(context)

        floatingips=neutron.list_floatingips(tenant_id=context.project_id)['floatingips']
        LOG.info('Existing floating ips: %s', floatingips)

        if public_ip:
            # TODO(ft): implement search in DB layer
            address = next((addr for addr in db_api.get_items(context,
                                                              'eipalloc')
                            if addr['public_ip'] == public_ip), None)

            if not CONF.disable_ec2_classic:
                if address and _is_address_valid(context, neutron, address):
                    msg = _('You must specify an association id when '
                            'unmapping an address from a VPC instance')
                    raise exception.InvalidParameterValue(msg)
                # NOTE(tikitavi): check the public IP exists to raise AWS
                # exception otherwise
                os_floating_ip = self.get_os_floating_ip_by_public_ip(
                    context, public_ip)
                os_ports = self.get_os_ports(context)
                os_instance_id = _get_os_instance_id(context, os_floating_ip,
                                                     os_ports)
                if os_instance_id:
                    nova = clients.nova(context)
                    nova.servers.remove_floating_ip(os_instance_id, public_ip)
                return None

            if not address:
                msg = _("The address '%(public_ip)s' does not belong to you.")
                raise exception.AuthFailure(msg % {'public_ip': public_ip})
            if 'network_interface_id' not in address:
                msg = _('You must specify an association id when unmapping '
                        'an address from a VPC instance')
                raise exception.InvalidParameterValue(msg)
            association_id = ec2utils.change_ec2_id_kind(address['id'],
                                                         'eipassoc')

        address = db_api.get_item_by_id(
            context, ec2utils.change_ec2_id_kind(association_id, 'eipalloc'))
        LOG.info('DB address: %s', address)
        if address is None or not _is_address_valid(context, neutron, address):
            raise exception.InvalidAssociationIDNotFound(
                    id=association_id)
        if 'network_interface_id' in address:
            with common.OnCrashCleaner() as cleaner:
                network_interface_id = address['network_interface_id']
                private_ip_address = address['private_ip_address']
                LOG.info('Disassociating %(private_ip_address)s from interface %(network_interface_id)s',
                         {'private_ip_address': private_ip_address, 'network_interface_id': network_interface_id})
                _disassociate_address_item(context, address)
                cleaner.addCleanup(_associate_address_item, context, address,
                                   network_interface_id, private_ip_address)

                update = neutron.update_floatingip(address['os_id'],
                                                   {'floatingip': {'port_id': None}})
                LOG.info('Neutron.update result is %s', update)
Example #2
0
def disassociate_route_table(context, association_id):
    subnet = db_api.get_item_by_id(
        context, ec2utils.change_ec2_id_kind(association_id, 'subnet'))
    if not subnet:
        vpc = db_api.get_item_by_id(
            context, ec2utils.change_ec2_id_kind(association_id, 'vpc'))
        if vpc is None:
            raise exception.InvalidAssociationIDNotFound(id=association_id)
        msg = _('Cannot disassociate the main route table association '
                '%(rtbassoc_id)s') % {'rtbassoc_id': association_id}
        raise exception.InvalidParameterValue(msg)
    if 'route_table_id' not in subnet:
        raise exception.InvalidAssociationIDNotFound(id=association_id)

    rollback_route_table_id = subnet['route_table_id']
    vpc = db_api.get_item_by_id(context, subnet['vpc_id'])
    main_route_table = db_api.get_item_by_id(context, vpc['route_table_id'])
    with common.OnCrashCleaner() as cleaner:
        _disassociate_subnet_item(context, subnet)
        cleaner.addCleanup(_associate_subnet_item, context, subnet,
                           rollback_route_table_id)

        _update_subnet_routes(context, cleaner, subnet, main_route_table)

    return True
Example #3
0
def disassociate_route_table(context, association_id):
    subnet = db_api.get_item_by_id(
        context, ec2utils.change_ec2_id_kind(association_id, 'subnet'))
    if not subnet:
        vpc = db_api.get_item_by_id(
            context, ec2utils.change_ec2_id_kind(association_id, 'vpc'))
        if vpc is None:
            raise exception.InvalidAssociationIDNotFound(id=association_id)
        msg = _('Cannot disassociate the main route table association '
                '%(rtbassoc_id)s') % {'rtbassoc_id': association_id}
        raise exception.InvalidParameterValue(msg)
    if 'route_table_id' not in subnet:
        raise exception.InvalidAssociationIDNotFound(id=association_id)

    rollback_route_table_id = subnet['route_table_id']
    vpc = db_api.get_item_by_id(context, subnet['vpc_id'])
    main_route_table = db_api.get_item_by_id(context, vpc['route_table_id'])
    with common.OnCrashCleaner() as cleaner:
        _disassociate_subnet_item(context, subnet)
        cleaner.addCleanup(_associate_subnet_item, context, subnet,
                           rollback_route_table_id)

        _update_subnet_routes(context, cleaner, subnet, main_route_table)

    return True
Example #4
0
    def disassociate_address(self, context, public_ip=None,
                             association_id=None):
        neutron = clients.neutron(context)

        if public_ip:
            # TODO(ft): implement search in DB layer
            address = next((addr for addr in db_api.get_items(context,
                                                              'eipalloc')
                            if addr['public_ip'] == public_ip), None)

            if not CONF.disable_ec2_classic:
                if address and _is_address_valid(context, neutron, address):
                    msg = _('You must specify an association id when '
                            'unmapping an address from a VPC instance')
                    raise exception.InvalidParameterValue(msg)
                # NOTE(tikitavi): check the public IP exists to raise AWS
                # exception otherwise
                os_floating_ip = self.get_os_floating_ip_by_public_ip(
                    context, public_ip)
                os_ports = self.get_os_ports(context)
                os_instance_id = _get_os_instance_id(context, os_floating_ip,
                                                     os_ports)
                if os_instance_id:
                    nova = clients.nova(context)
                    nova.servers.remove_floating_ip(os_instance_id, public_ip)
                return None

            if not address:
                msg = _("The address '%(public_ip)s' does not belong to you.")
                raise exception.AuthFailure(msg % {'public_ip': public_ip})
            if 'network_interface_id' not in address:
                msg = _('You must specify an association id when unmapping '
                        'an address from a VPC instance')
                raise exception.InvalidParameterValue(msg)
            association_id = ec2utils.change_ec2_id_kind(address['id'],
                                                         'eipassoc')

        address = db_api.get_item_by_id(
            context, ec2utils.change_ec2_id_kind(association_id, 'eipalloc'))
        if address is None or not _is_address_valid(context, neutron, address):
            raise exception.InvalidAssociationIDNotFound(
                    id=association_id)
        if 'network_interface_id' in address:
            with common.OnCrashCleaner() as cleaner:
                network_interface_id = address['network_interface_id']
                private_ip_address = address['private_ip_address']
                _disassociate_address_item(context, address)
                cleaner.addCleanup(_associate_address_item, context, address,
                                   network_interface_id, private_ip_address)

                neutron.update_floatingip(address['os_id'],
                                          {'floatingip': {'port_id': None}})
def replace_route_table_association(context, association_id, route_table_id):
    route_table = ec2utils.get_db_item(context, route_table_id)
    if route_table['vpc_id'] == ec2utils.change_ec2_id_kind(
            association_id, 'vpc'):
        vpc = db_api.get_item_by_id(
            context, ec2utils.change_ec2_id_kind(association_id, 'vpc'))
        if vpc is None:
            raise exception.InvalidAssociationIDNotFound(id=association_id)

        rollabck_route_table_object = db_api.get_item_by_id(
            context, vpc['route_table_id'])
        with common.OnCrashCleaner() as cleaner:
            _associate_vpc_item(context, vpc, route_table['id'])
            cleaner.addCleanup(_associate_vpc_item, context, vpc,
                               rollabck_route_table_object['id'])

            # NOTE(ft): this can cause unnecessary update of subnets, which are
            # associated with the route table
            _update_routes_in_associated_subnets(context,
                                                 route_table,
                                                 cleaner,
                                                 rollabck_route_table_object,
                                                 is_main=True)
    else:
        subnet = db_api.get_item_by_id(
            context, ec2utils.change_ec2_id_kind(association_id, 'subnet'))
        if subnet is None or 'route_table_id' not in subnet:
            raise exception.InvalidAssociationIDNotFound(id=association_id)
        if subnet['vpc_id'] != route_table['vpc_id']:
            msg = _('Route table association %(rtbassoc_id)s and route table '
                    '%(rtb_id)s belong to different networks')
            msg = msg % {
                'rtbassoc_id': association_id,
                'rtb_id': route_table_id
            }
            raise exception.InvalidParameterValue(msg)

        rollabck_route_table_object = db_api.get_item_by_id(
            context, subnet['route_table_id'])
        with common.OnCrashCleaner() as cleaner:
            _associate_subnet_item(context, subnet, route_table['id'])
            cleaner.addCleanup(_associate_subnet_item, context, subnet,
                               rollabck_route_table_object['id'])

            _update_subnet_host_routes(
                context,
                subnet,
                route_table,
                cleaner=cleaner,
                rollback_route_table_object=rollabck_route_table_object)

    return {'newAssociationId': association_id}
    def test_detach_network_interface_invalid_parameters(self):
        # NOTE(ft): eni is not found
        self.set_mock_db_items()
        self.assert_execution_error(
            'InvalidAttachmentID.NotFound', 'DetachNetworkInterface',
            {'AttachmentId': ec2utils.change_ec2_id_kind(
                    fakes.ID_EC2_NETWORK_INTERFACE_2, 'eni-attach')})

        # NOTE(ft): eni is attached with device index = 0
        self.set_mock_db_items(fakes.DB_NETWORK_INTERFACE_2)
        self.assert_execution_error(
            'OperationNotPermitted', 'DetachNetworkInterface',
            {'AttachmentId': ec2utils.change_ec2_id_kind(
                    fakes.ID_EC2_NETWORK_INTERFACE_2, 'eni-attach')})
Example #7
0
    def disassociate_address(self,
                             context,
                             public_ip=None,
                             association_id=None):
        neutron = clients.neutron(context)

        if public_ip:
            # TODO(ft): implement search in DB layer
            address = next((addr
                            for addr in db_api.get_items(context, 'eipalloc')
                            if addr['public_ip'] == public_ip), None)

            if not CONF.disable_ec2_classic:
                if address and _is_address_valid(context, neutron, address):
                    msg = _('You must specify an association id when '
                            'unmapping an address from a VPC instance')
                    raise exception.InvalidParameterValue(msg)
                # NOTE(ft): association_id is unused in EC2 Classic mode,
                # but it's passed there to validate its emptiness in one place
                return AddressEngineNova().disassociate_address(
                    context,
                    public_ip=public_ip,
                    association_id=association_id)

            if not address:
                msg = _("The address '%(public_ip)s' does not belong to you.")
                raise exception.AuthFailure(msg % {'public_ip': public_ip})
            if 'network_interface_id' not in address:
                msg = _('You must specify an association id when unmapping '
                        'an address from a VPC instance')
                raise exception.InvalidParameterValue(msg)
            association_id = ec2utils.change_ec2_id_kind(
                address['id'], 'eipassoc')

        address = db_api.get_item_by_id(
            context, ec2utils.change_ec2_id_kind(association_id, 'eipalloc'))
        if address is None or not _is_address_valid(context, neutron, address):
            raise exception.InvalidAssociationIDNotFound(id=association_id)
        if 'network_interface_id' in address:
            with common.OnCrashCleaner() as cleaner:
                network_interface_id = address['network_interface_id']
                private_ip_address = address['private_ip_address']
                _disassociate_address_item(context, address)
                cleaner.addCleanup(_associate_address_item, context, address,
                                   network_interface_id, private_ip_address)

                neutron.update_floatingip(address['os_id'],
                                          {'floatingip': {
                                              'port_id': None
                                          }})
def associate_route_table(context, route_table_id, subnet_id):
    route_table = ec2utils.get_db_item(context, route_table_id)
    subnet = ec2utils.get_db_item(context, subnet_id)
    if route_table['vpc_id'] != subnet['vpc_id']:
        msg = _('Route table %(rtb_id)s and subnet %(subnet_id)s belong to '
                'different networks')
        msg = msg % {'rtb_id': route_table_id, 'subnet_id': subnet_id}
        raise exception.InvalidParameterValue(msg)
    if 'route_table_id' in subnet:
        msg = _('The specified association for route table %(rtb_id)s '
                'conflicts with an existing association')
        msg = msg % {'rtb_id': route_table_id}
        raise exception.ResourceAlreadyAssociated(msg)

    vpc = db_api.get_item_by_id(context, subnet['vpc_id'])
    main_route_table = db_api.get_item_by_id(context, vpc['route_table_id'])
    with common.OnCrashCleaner() as cleaner:
        _associate_subnet_item(context, subnet, route_table['id'])
        cleaner.addCleanup(_disassociate_subnet_item, context, subnet)

        _update_subnet_host_routes(
            context,
            subnet,
            route_table,
            cleaner=cleaner,
            rollback_route_table_object=main_route_table)

    return {
        'associationId': ec2utils.change_ec2_id_kind(subnet['id'], 'rtbassoc')
    }
Example #9
0
def attach_network_interface(context, network_interface_id,
                             instance_id, device_index):
    network_interface = ec2utils.get_db_item(context, network_interface_id)
    if 'instance_id' in network_interface:
        raise exception.InvalidParameterValue(
            _("Network interface '%(id)s' is currently in use.") %
            {'id': network_interface_id})
    os_instance_id = ec2utils.get_db_item(context, instance_id)['os_id']
    # TODO(Alex) Check that the instance is not yet attached to another VPC
    # TODO(Alex) Check that the instance is "our", not created via nova
    # (which means that it doesn't belong to any VPC and can't be attached)
    if any(eni['device_index'] == device_index
           for eni in db_api.get_items(context, 'eni')
           if eni.get('instance_id') == instance_id):
        raise exception.InvalidParameterValue(
            _("Instance '%(id)s' already has an interface attached at "
              "device index '%(index)s'.") % {'id': instance_id,
                                              'index': device_index})
    neutron = clients.neutron(context)
    os_port = neutron.show_port(network_interface['os_id'])['port']
    nova = clients.nova(context)
    with common.OnCrashCleaner() as cleaner:
        # TODO(Alex) nova inserts compute:%availability_zone into device_owner
        #                              'device_owner': 'compute:None'}})
        _attach_network_interface_item(context, network_interface,
                                       instance_id, device_index)
        cleaner.addCleanup(_detach_network_interface_item, context,
                           network_interface)
        nova.servers.interface_attach(os_instance_id, os_port['id'],
                                      None, None)
    return {'attachmentId': ec2utils.change_ec2_id_kind(
                    network_interface['id'], 'eni-attach')}
    def test_modify_network_interface_attribute_invalid_parameters(self):
        self.assert_execution_error(
            'InvalidParameterCombination', 'ModifyNetworkInterfaceAttribute',
            {'NetworkInterfaceId': fakes.ID_EC2_NETWORK_INTERFACE_1,
             'Description.Value': 'New description',
             'SourceDestCheck.Value': 'True'})

        self.set_mock_db_items(fakes.DB_NETWORK_INTERFACE_1,
                               fakes.DB_NETWORK_INTERFACE_2)

        self.assert_execution_error(
            'MissingParameter', 'ModifyNetworkInterfaceAttribute',
            {'NetworkInterfaceId': fakes.ID_EC2_NETWORK_INTERFACE_2,
             'Attachment.DeleteOnTermination': 'True'})

        self.assert_execution_error(
            'MissingParameter', 'ModifyNetworkInterfaceAttribute',
            {'NetworkInterfaceId': fakes.ID_EC2_NETWORK_INTERFACE_2,
             'Attachment.AttachmentId': (
                 fakes.ID_EC2_NETWORK_INTERFACE_2_ATTACH)})

        self.assert_execution_error(
            'InvalidAttachmentID.NotFound', 'ModifyNetworkInterfaceAttribute',
            {'NetworkInterfaceId': fakes.ID_EC2_NETWORK_INTERFACE_1,
             'Attachment.AttachmentId': (
                 fakes.ID_EC2_NETWORK_INTERFACE_2_ATTACH),
             'Attachment.DeleteOnTermination': 'True'})

        self.assert_execution_error(
            'InvalidAttachmentID.NotFound', 'ModifyNetworkInterfaceAttribute',
            {'NetworkInterfaceId': fakes.ID_EC2_NETWORK_INTERFACE_2,
             'Attachment.AttachmentId': ec2utils.change_ec2_id_kind(
                 fakes.ID_EC2_NETWORK_INTERFACE_1, 'eni-attach'),
             'Attachment.DeleteOnTermination': 'True'})
def attach_network_interface(context, network_interface_id,
                             instance_id, device_index):
    network_interface = ec2utils.get_db_item(context, network_interface_id)
    if 'instance_id' in network_interface:
        raise exception.InvalidParameterValue(
            _("Network interface '%(id)s' is currently in use.") %
            {'id': network_interface_id})
    os_instance_id = ec2utils.get_db_item(context, instance_id)['os_id']
    # TODO(Alex) Check that the instance is not yet attached to another VPC
    # TODO(Alex) Check that the instance is "our", not created via nova
    # (which means that it doesn't belong to any VPC and can't be attached)
    if any(eni['device_index'] == device_index
           for eni in db_api.get_items(context, 'eni')
           if eni.get('instance_id') == instance_id):
        raise exception.InvalidParameterValue(
            _("Instance '%(id)s' already has an interface attached at "
              "device index '%(index)s'.") % {'id': instance_id,
                                              'index': device_index})
    neutron = clients.neutron(context)
    os_port = neutron.show_port(network_interface['os_id'])['port']
    nova = clients.nova(context)
    with common.OnCrashCleaner() as cleaner:
        # TODO(Alex) nova inserts compute:%availability_zone into device_owner
        #                              'device_owner': 'compute:None'}})
        _attach_network_interface_item(context, network_interface,
                                       instance_id, device_index)
        cleaner.addCleanup(_detach_network_interface_item, context,
                           network_interface)
        nova.servers.interface_attach(os_instance_id, os_port['id'],
                                      None, None)
    return {'attachmentId': ec2utils.change_ec2_id_kind(
                    network_interface['id'], 'eni-attach')}
Example #12
0
def _create_security_group(context, group_name, group_description,
                           vpc_id=None, default=False):
    neutron = clients.neutron(context)
    with common.OnCrashCleaner() as cleaner:
        try:
            secgroup_body = (
                {'security_group': {'name': group_name,
                                    'description': group_description}})
            os_security_group = neutron.create_security_group(
                secgroup_body)['security_group']
        except neutron_exception.OverQuotaClient:
            raise exception.ResourceLimitExceeded(resource='security groups')
        cleaner.addCleanup(neutron.delete_security_group,
                           os_security_group['id'])
        if vpc_id:
            # NOTE(Alex) Check if such vpc exists
            ec2utils.get_db_item(context, vpc_id)
        item = {'vpc_id': vpc_id, 'os_id': os_security_group['id']}
        if not default:
            security_group = db_api.add_item(context, 'sg', item)
        else:
            item['id'] = ec2utils.change_ec2_id_kind(vpc_id, 'sg')
            # NOTE(andrey-mp): try to add item with specific id
            # and catch exception if it exists
            security_group = db_api.restore_item(context, 'sg', item)
        return {'return': 'true',
                'groupId': security_group['id']}
Example #13
0
def _create_security_group(context, group_name, group_description,
                           vpc_id=None, default=False):
    neutron = clients.neutron(context)
    with common.OnCrashCleaner() as cleaner:
        try:
            secgroup_body = (
                {'security_group': {'name': group_name,
                                    'description': group_description}})
            os_security_group = neutron.create_security_group(
                secgroup_body)['security_group']
        except neutron_exception.OverQuotaClient:
            raise exception.ResourceLimitExceeded(resource='security groups')
        cleaner.addCleanup(neutron.delete_security_group,
                           os_security_group['id'])
        if vpc_id:
            # NOTE(Alex) Check if such vpc exists
            ec2utils.get_db_item(context, vpc_id)
        item = {'vpc_id': vpc_id, 'os_id': os_security_group['id']}
        if not default:
            security_group = db_api.add_item(context, 'sg', item)
        else:
            item['id'] = ec2utils.change_ec2_id_kind(vpc_id, 'sg')
            # NOTE(andrey-mp): try to add item with specific id
            # and catch exception if it exists
            security_group = db_api.restore_item(context, 'sg', item)
        return {'return': 'true',
                'groupId': security_group['id']}
Example #14
0
def _create_security_group(context,
                           group_name,
                           group_description,
                           vpc_id=None,
                           default=False):
    nova = clients.nova(context)
    with common.OnCrashCleaner() as cleaner:
        try:
            os_security_group = nova.security_groups.create(
                group_name, group_description)
        except nova_exception.OverLimit:
            raise exception.ResourceLimitExceeded(resource='security groups')
        cleaner.addCleanup(nova.security_groups.delete, os_security_group.id)
        if vpc_id:
            # NOTE(Alex) Check if such vpc exists
            ec2utils.get_db_item(context, vpc_id)
        item = {'vpc_id': vpc_id, 'os_id': os_security_group.id}
        if not default:
            security_group = db_api.add_item(context, 'sg', item)
        else:
            item['id'] = ec2utils.change_ec2_id_kind(vpc_id, 'sg')
            # NOTE(andrey-mp): try to add item with specific id
            # and catch exception if it exists
            security_group = db_api.restore_item(context, 'sg', item)
        return {'return': 'true', 'groupId': security_group['id']}
Example #15
0
    def disassociate_address(self, context, public_ip=None,
                             association_id=None):
        neutron = clients.neutron(context)
        if public_ip:
            # TODO(ft): implement search in DB layer
            address = next((addr for addr in db_api.get_items(context,
                                                              'eipalloc')
                            if addr['public_ip'] == public_ip), None)
            if address and _is_address_valid(context, neutron, address):
                msg = _('You must specify an association id when unmapping '
                        'an address from a VPC instance')
                raise exception.InvalidParameterValue(msg)
            # NOTE(ft): association_id is unused in EC2 Classic mode, but it's
            # passed there to validate its emptiness in one place
            return AddressEngineNova().disassociate_address(
                    context, public_ip=public_ip,
                    association_id=association_id)

        address = db_api.get_item_by_id(
            context, ec2utils.change_ec2_id_kind(association_id, 'eipalloc'))
        if address is None or not _is_address_valid(context, neutron, address):
            raise exception.InvalidAssociationIDNotFound(
                    id=association_id)
        if 'network_interface_id' in address:
            with common.OnCrashCleaner() as cleaner:
                network_interface_id = address['network_interface_id']
                private_ip_address = address['private_ip_address']
                _disassociate_address_item(context, address)
                cleaner.addCleanup(_associate_address_item, context, address,
                                   network_interface_id, private_ip_address)

                neutron.update_floatingip(address['os_id'],
                                          {'floatingip': {'port_id': None}})
Example #16
0
def _format_address(context, address, os_floating_ip, os_ports=[],
                    db_instances_dict=None):
    ec2_address = {'publicIp': os_floating_ip['floating_ip_address']}
    fixed_ip_address = os_floating_ip.get('fixed_ip_address')
    if fixed_ip_address:
        ec2_address['privateIpAddress'] = fixed_ip_address
        port_id = os_floating_ip.get('port_id')
        os_fip = os_floating_ip.get('instance_id')
        if port_id:
            port = next((port for port in os_ports
                         if port['id'] == port_id), None)
            if port and port.get('device_id'):
                ec2_address['instanceId'] = (
                    _get_instance_ec2_id_by_os_id(context, port['device_id'],
                                                  db_instances_dict))
        elif os_fip:
            ec2_address['instanceId'] = (
                _get_instance_ec2_id_by_os_id(context, os_fip,
                                              db_instances_dict))
    if not address:
        ec2_address['domain'] = 'standard'
    else:
        ec2_address['domain'] = 'vpc'
        ec2_address['allocationId'] = address['id']
        if 'network_interface_id' in address:
            ec2_address.update({
                    'associationId': ec2utils.change_ec2_id_kind(
                            ec2_address['allocationId'], 'eipassoc'),
                    'networkInterfaceId': address['network_interface_id'],
                    'networkInterfaceOwnerId': context.project_id})
    return ec2_address
Example #17
0
def detach_network_interface(context, attachment_id, force=None):
    network_interface = db_api.get_item_by_id(
        context, ec2utils.change_ec2_id_kind(attachment_id, 'eni'))
    if not network_interface or 'instance_id' not in network_interface:
        raise exception.InvalidAttachmentIDNotFound(id=attachment_id)
    if network_interface['device_index'] == 0:
        raise exception.OperationNotPermitted(
            _('The network interface at device index 0 cannot be detached.'))
    neutron = clients.neutron(context)
    os_port = neutron.show_port(network_interface['os_id'])['port']
    with common.OnCrashCleaner() as cleaner:
        instance_id = network_interface['instance_id']
        device_index = network_interface['device_index']
        attach_time = network_interface['attach_time']
        delete_on_termination = network_interface['delete_on_termination']
        _detach_network_interface_item(context, network_interface)
        cleaner.addCleanup(_attach_network_interface_item, context,
                           network_interface, instance_id, device_index,
                           attach_time, delete_on_termination)
        neutron.update_port(os_port['id'],
                            {'port': {
                                'device_id': '',
                                'device_owner': ''
                            }})
    return True
    def test_detach_network_interface_invalid_parameters(self):
        # NOTE(ft): eni is not found
        self.set_mock_db_items()
        self.assert_execution_error(
            'InvalidAttachmentID.NotFound', 'DetachNetworkInterface', {
                'AttachmentId':
                ec2utils.change_ec2_id_kind(fakes.ID_EC2_NETWORK_INTERFACE_2,
                                            'eni-attach')
            })

        # NOTE(ft): eni is attached with device index = 0
        self.set_mock_db_items(fakes.DB_NETWORK_INTERFACE_2)
        self.assert_execution_error(
            'OperationNotPermitted', 'DetachNetworkInterface', {
                'AttachmentId':
                ec2utils.change_ec2_id_kind(fakes.ID_EC2_NETWORK_INTERFACE_2,
                                            'eni-attach')
            })
    def test_replace_route_table_association_invalid_parameters(self):
        def do_check(params, error_code):
            self.assert_execution_error(error_code,
                                        'ReplaceRouteTableAssociation', params)

        self.set_mock_db_items()
        do_check(
            {
                'AssociationId': fakes.ID_EC2_ROUTE_TABLE_ASSOCIATION_1,
                'RouteTableId': fakes.ID_EC2_ROUTE_TABLE_1
            }, 'InvalidRouteTableID.NotFound')

        # NOTE(ft): association with vpc is obsolete
        self.set_mock_db_items(fakes.DB_ROUTE_TABLE_1)
        do_check(
            {
                'AssociationId': fakes.ID_EC2_ROUTE_TABLE_ASSOCIATION_1,
                'RouteTableId': fakes.ID_EC2_ROUTE_TABLE_1
            }, 'InvalidAssociationID.NotFound')

        # NOTE(ft): association with subnet is obsolete (no subnet)
        self.set_mock_db_items(fakes.DB_ROUTE_TABLE_3)
        do_check(
            {
                'AssociationId': fakes.ID_EC2_ROUTE_TABLE_ASSOCIATION_3,
                'RouteTableId': fakes.ID_EC2_ROUTE_TABLE_3
            }, 'InvalidAssociationID.NotFound')

        # NOTE(ft): association with subnet is obsolete (subnet is
        # disassociated)
        self.set_mock_db_items(
            fakes.DB_ROUTE_TABLE_3,
            tools.purge_dict(fakes.DB_SUBNET_2, ['route_table_id']))
        do_check(
            {
                'AssociationId': fakes.ID_EC2_ROUTE_TABLE_ASSOCIATION_3,
                'RouteTableId': fakes.ID_EC2_ROUTE_TABLE_3
            }, 'InvalidAssociationID.NotFound')

        # NOTE(ft): association belongs to different vpc
        id_ec2_subnet_vpc_2 = fakes.random_ec2_id('subnet')
        db_subnet_vpc_2 = {
            'id': id_ec2_subnet_vpc_2,
            'os_id': fakes.random_os_id(),
            'vpc_id': fakes.ID_EC2_VPC_2,
            'route_table_id': fakes.random_ec2_id('rtb')
        }
        self.set_mock_db_items(fakes.DB_ROUTE_TABLE_2, db_subnet_vpc_2)
        do_check(
            {
                'AssociationId':
                ec2utils.change_ec2_id_kind(id_ec2_subnet_vpc_2, 'rtbassoc'),
                'RouteTableId':
                fakes.ID_EC2_ROUTE_TABLE_2
            }, 'InvalidParameterValue')
Example #20
0
    def release_address(self, context, public_ip, allocation_id):
        neutron = clients.neutron(context)
        if public_ip:
            # TODO(ft): implement search in DB layer
            address = next((addr for addr in
                            db_api.get_items(context, 'eipalloc')
                            if addr['public_ip'] == public_ip), None)
            if address and _is_address_valid(context, neutron, address):
                msg = _('You must specify an allocation id when releasing a '
                        'VPC elastic IP address')
                raise exception.InvalidParameterValue(msg)
            os_floating_ip = self.get_os_floating_ip_by_public_ip(context,
                                                                  public_ip)
            try:
                neutron.delete_floatingip(os_floating_ip['id'])
            except neutron_exception.NotFound:
                pass
            return

        address = ec2utils.get_db_item(context, allocation_id)
        if not _is_address_valid(context, neutron, address):
            raise exception.InvalidAllocationIDNotFound(
                id=allocation_id)

        if 'network_interface_id' in address:
            if CONF.disable_ec2_classic:
                network_interface_id = address['network_interface_id']
                network_interface = db_api.get_item_by_id(context,
                                                          network_interface_id)
                default_vpc = ec2utils.check_and_create_default_vpc(context)
                if default_vpc:
                    default_vpc_id = default_vpc['id']
                if (network_interface and
                        network_interface['vpc_id'] == default_vpc_id):
                    association_id = ec2utils.change_ec2_id_kind(address['id'],
                                                                 'eipassoc')
                    self.disassociate_address(
                        context, association_id=association_id)
                else:
                    raise exception.InvalidIPAddressInUse(
                        ip_address=address['public_ip'])
            else:
                raise exception.InvalidIPAddressInUse(
                    ip_address=address['public_ip'])

        with common.OnCrashCleaner() as cleaner:
            db_api.delete_item(context, address['id'])
            cleaner.addCleanup(db_api.restore_item, context,
                               'eipalloc', address)
            try:
                neutron.delete_floatingip(address['os_id'])
            except neutron_exception.NotFound:
                pass
Example #21
0
    def release_address(self, context, public_ip, allocation_id):
        neutron = clients.neutron(context)
        if public_ip:
            # TODO(ft): implement search in DB layer
            address = next((addr for addr in
                            db_api.get_items(context, 'eipalloc')
                            if addr['public_ip'] == public_ip), None)
            if address and _is_address_valid(context, neutron, address):
                msg = _('You must specify an allocation id when releasing a '
                        'VPC elastic IP address')
                raise exception.InvalidParameterValue(msg)
            os_floating_ip = self.get_os_floating_ip_by_public_ip(context,
                                                                  public_ip)
            try:
                neutron.delete_floatingip(os_floating_ip['id'])
            except neutron_exception.NotFound:
                pass
            return

        address = ec2utils.get_db_item(context, allocation_id)
        if not _is_address_valid(context, neutron, address):
            raise exception.InvalidAllocationIDNotFound(
                id=allocation_id)

        if 'network_interface_id' in address:
            if CONF.disable_ec2_classic:
                network_interface_id = address['network_interface_id']
                network_interface = db_api.get_item_by_id(context,
                                                          network_interface_id)
                default_vpc = ec2utils.check_and_create_default_vpc(context)
                if default_vpc:
                    default_vpc_id = default_vpc['id']
                if (network_interface and
                        network_interface['vpc_id'] == default_vpc_id):
                    association_id = ec2utils.change_ec2_id_kind(address['id'],
                                                                 'eipassoc')
                    self.disassociate_address(
                        context, association_id=association_id)
                else:
                    raise exception.InvalidIPAddressInUse(
                        ip_address=address['public_ip'])
            else:
                raise exception.InvalidIPAddressInUse(
                    ip_address=address['public_ip'])

        with common.OnCrashCleaner() as cleaner:
            db_api.delete_item(context, address['id'])
            cleaner.addCleanup(db_api.restore_item, context,
                               'eipalloc', address)
            try:
                neutron.delete_floatingip(address['os_id'])
            except neutron_exception.NotFound:
                pass
Example #22
0
def replace_route_table_association(context, association_id, route_table_id):
    route_table = ec2utils.get_db_item(context, route_table_id)
    if route_table['vpc_id'] == ec2utils.change_ec2_id_kind(
            association_id, 'vpc'):
        vpc = db_api.get_item_by_id(
            context, ec2utils.change_ec2_id_kind(association_id, 'vpc'))
        if vpc is None:
            raise exception.InvalidAssociationIDNotFound(id=association_id)

        rollback_route_table_id = vpc['route_table_id']
        with common.OnCrashCleaner() as cleaner:
            _associate_vpc_item(context, vpc, route_table['id'])
            cleaner.addCleanup(_associate_vpc_item, context, vpc,
                               rollback_route_table_id)

            _update_routes_in_associated_subnets(
                context, cleaner, route_table, default_associations_only=True)
    else:
        subnet = db_api.get_item_by_id(
            context, ec2utils.change_ec2_id_kind(association_id, 'subnet'))
        if subnet is None or 'route_table_id' not in subnet:
            raise exception.InvalidAssociationIDNotFound(id=association_id)
        if subnet['vpc_id'] != route_table['vpc_id']:
            msg = _('Route table association %(rtbassoc_id)s and route table '
                    '%(rtb_id)s belong to different networks')
            msg = msg % {
                'rtbassoc_id': association_id,
                'rtb_id': route_table_id
            }
            raise exception.InvalidParameterValue(msg)

        rollback_route_table_id = subnet['route_table_id']
        with common.OnCrashCleaner() as cleaner:
            _associate_subnet_item(context, subnet, route_table['id'])
            cleaner.addCleanup(_associate_subnet_item, context, subnet,
                               rollback_route_table_id)

            _update_subnet_routes(context, cleaner, subnet, route_table)

    return {'newAssociationId': association_id}
Example #23
0
def replace_route_table_association(context, association_id, route_table_id):
    route_table = ec2utils.get_db_item(context, route_table_id)
    if route_table['vpc_id'] == ec2utils.change_ec2_id_kind(association_id,
                                                            'vpc'):
        vpc = db_api.get_item_by_id(
            context, ec2utils.change_ec2_id_kind(association_id, 'vpc'))
        if vpc is None:
            raise exception.InvalidAssociationIDNotFound(id=association_id)

        rollback_route_table_id = vpc['route_table_id']
        with common.OnCrashCleaner() as cleaner:
            _associate_vpc_item(context, vpc, route_table['id'])
            cleaner.addCleanup(_associate_vpc_item, context, vpc,
                               rollback_route_table_id)

            _update_routes_in_associated_subnets(
                context, cleaner, route_table, default_associations_only=True)
    else:
        subnet = db_api.get_item_by_id(
            context, ec2utils.change_ec2_id_kind(association_id, 'subnet'))
        if subnet is None or 'route_table_id' not in subnet:
            raise exception.InvalidAssociationIDNotFound(id=association_id)
        if subnet['vpc_id'] != route_table['vpc_id']:
            msg = _('Route table association %(rtbassoc_id)s and route table '
                    '%(rtb_id)s belong to different networks')
            msg = msg % {'rtbassoc_id': association_id,
                         'rtb_id': route_table_id}
            raise exception.InvalidParameterValue(msg)

        rollback_route_table_id = subnet['route_table_id']
        with common.OnCrashCleaner() as cleaner:
            _associate_subnet_item(context, subnet, route_table['id'])
            cleaner.addCleanup(_associate_subnet_item, context, subnet,
                               rollback_route_table_id)

            _update_subnet_routes(context, cleaner, subnet, route_table)

    return {'newAssociationId': association_id}
Example #24
0
def modify_network_interface_attribute(context,
                                       network_interface_id,
                                       description=None,
                                       source_dest_check=None,
                                       security_group_id=None,
                                       attachment=None):
    params_count = (int(description is not None) +
                    int(source_dest_check is not None) +
                    int(security_group_id is not None) +
                    int(attachment is not None))
    if params_count != 1:
        raise exception.InvalidParameterCombination(
            'Multiple attributes specified')
    network_interface = ec2utils.get_db_item(context, network_interface_id)
    if description is not None:
        network_interface['description'] = description
        db_api.update_item(context, network_interface)
    neutron = clients.neutron(context)
    if security_group_id is not None:
        os_groups = [
            sg['os_id']
            for sg in ec2utils.get_db_items(context, 'sg', security_group_id)
        ]
        neutron.update_port(network_interface['os_id'],
                            {'port': {
                                'security_groups': os_groups
                            }})
    if source_dest_check is not None:
        allowed = [] if source_dest_check else [{'ip_address': '0.0.0.0/0'}]
        neutron.update_port(network_interface['os_id'],
                            {'port': {
                                'allowed_address_pairs': allowed
                            }})
        network_interface['source_dest_check'] = source_dest_check
        db_api.update_item(context, network_interface)
    if attachment:
        attachment_id = attachment.get('attachment_id')
        delete_on_termination = attachment.get('delete_on_termination')
        if attachment_id is None or delete_on_termination is None:
            raise exception.MissingParameter(
                _('The request must contain the parameter attachment '
                  'deleteOnTermination'))
        attachment_id_own = ec2utils.change_ec2_id_kind(
            network_interface['id'], 'eni-attach')
        if ('instance_id' not in network_interface
                or attachment_id_own != attachment_id):
            raise exception.InvalidAttachmentIDNotFound(id=attachment_id)
        network_interface['delete_on_termination'] = delete_on_termination
        db_api.update_item(context, network_interface)
    return True
    def test_modify_network_interface_attribute_invalid_parameters(self):
        self.assert_execution_error(
            'InvalidParameterCombination', 'ModifyNetworkInterfaceAttribute', {
                'NetworkInterfaceId': fakes.ID_EC2_NETWORK_INTERFACE_1,
                'Description.Value': 'New description',
                'SourceDestCheck.Value': 'True'
            })

        self.set_mock_db_items(fakes.DB_NETWORK_INTERFACE_1,
                               fakes.DB_NETWORK_INTERFACE_2)

        self.assert_execution_error(
            'MissingParameter', 'ModifyNetworkInterfaceAttribute', {
                'NetworkInterfaceId': fakes.ID_EC2_NETWORK_INTERFACE_2,
                'Attachment.DeleteOnTermination': 'True'
            })

        self.assert_execution_error(
            'MissingParameter', 'ModifyNetworkInterfaceAttribute', {
                'NetworkInterfaceId':
                fakes.ID_EC2_NETWORK_INTERFACE_2,
                'Attachment.AttachmentId':
                (fakes.ID_EC2_NETWORK_INTERFACE_2_ATTACH)
            })

        self.assert_execution_error(
            'InvalidAttachmentID.NotFound', 'ModifyNetworkInterfaceAttribute',
            {
                'NetworkInterfaceId':
                fakes.ID_EC2_NETWORK_INTERFACE_1,
                'Attachment.AttachmentId':
                (fakes.ID_EC2_NETWORK_INTERFACE_2_ATTACH),
                'Attachment.DeleteOnTermination':
                'True'
            })

        self.assert_execution_error(
            'InvalidAttachmentID.NotFound', 'ModifyNetworkInterfaceAttribute',
            {
                'NetworkInterfaceId':
                fakes.ID_EC2_NETWORK_INTERFACE_2,
                'Attachment.AttachmentId':
                ec2utils.change_ec2_id_kind(fakes.ID_EC2_NETWORK_INTERFACE_1,
                                            'eni-attach'),
                'Attachment.DeleteOnTermination':
                'True'
            })
def modify_network_interface_attribute(context, network_interface_id,
                                       description=None,
                                       source_dest_check=None,
                                       security_group_id=None,
                                       attachment=None):
    params_count = (
        int(description is not None) +
        int(source_dest_check is not None) +
        int(security_group_id is not None) +
        int(attachment is not None))
    if params_count != 1:
        raise exception.InvalidParameterCombination(
            'Multiple attributes specified')
    network_interface = ec2utils.get_db_item(context, network_interface_id)
    if description is not None:
        network_interface['description'] = description
        db_api.update_item(context, network_interface)
    neutron = clients.neutron(context)
    if security_group_id is not None:
        os_groups = [sg['os_id']
                     for sg in ec2utils.get_db_items(context, 'sg',
                                                     security_group_id)]
        neutron.update_port(network_interface['os_id'],
                            {'port': {'security_groups': os_groups}})
    if source_dest_check is not None:
        allowed = [] if source_dest_check else [{'ip_address': '0.0.0.0/0'}]
        neutron.update_port(network_interface['os_id'],
                            {'port': {'allowed_address_pairs': allowed}})
        network_interface['source_dest_check'] = source_dest_check
        db_api.update_item(context, network_interface)
    if attachment:
        attachment_id = attachment.get('attachment_id')
        delete_on_termination = attachment.get('delete_on_termination')
        if attachment_id is None or delete_on_termination is None:
            raise exception.MissingParameter(
                _('The request must contain the parameter attachment '
                  'deleteOnTermination'))
        attachment_id_own = ec2utils.change_ec2_id_kind(
                network_interface['id'], 'eni-attach')
        if ('instance_id' not in network_interface
                or attachment_id_own != attachment_id):
            raise exception.InvalidAttachmentIDNotFound(id=attachment_id)
        network_interface['delete_on_termination'] = delete_on_termination
        db_api.update_item(context, network_interface)
    return True
 def test_detach_network_interface(self):
     network_interface = tools.update_dict(fakes.DB_NETWORK_INTERFACE_2,
                                           {'device_index': 1})
     self.set_mock_db_items(network_interface)
     self.neutron.show_port.return_value = (
         {'port': fakes.OS_PORT_2})
     self.execute(
         'DetachNetworkInterface',
         {'AttachmentId': ec2utils.change_ec2_id_kind(
                 fakes.ID_EC2_NETWORK_INTERFACE_2, 'eni-attach')})
     self.neutron.update_port.assert_called_once_with(
         fakes.ID_OS_PORT_2,
         {'port': {'device_id': '',
                   'device_owner': ''}}
     )
     self.db_api.update_item.assert_called_once_with(
         mock.ANY,
         tools.purge_dict(fakes.DB_NETWORK_INTERFACE_2,
                          {'device_index',
                           'instance_id',
                           'delete_on_termination',
                           'attach_time'}))
def detach_network_interface(context, attachment_id, force=None):
    network_interface = db_api.get_item_by_id(
            context, ec2utils.change_ec2_id_kind(attachment_id, 'eni'))
    if not network_interface or 'instance_id' not in network_interface:
        raise exception.InvalidAttachmentIDNotFound(id=attachment_id)
    if network_interface['device_index'] == 0:
        raise exception.OperationNotPermitted(
            _('The network interface at device index 0 cannot be detached.'))
    neutron = clients.neutron(context)
    os_port = neutron.show_port(network_interface['os_id'])['port']
    with common.OnCrashCleaner() as cleaner:
        instance_id = network_interface['instance_id']
        device_index = network_interface['device_index']
        attach_time = network_interface['attach_time']
        delete_on_termination = network_interface['delete_on_termination']
        _detach_network_interface_item(context, network_interface)
        cleaner.addCleanup(_attach_network_interface_item,
                           context, network_interface, instance_id,
                           device_index, attach_time, delete_on_termination)
        neutron.update_port(os_port['id'],
                            {'port': {'device_id': '',
                                      'device_owner': ''}})
    return True
Example #29
0
def associate_route_table(context, route_table_id, subnet_id):
    route_table = ec2utils.get_db_item(context, route_table_id)
    subnet = ec2utils.get_db_item(context, subnet_id)
    if route_table['vpc_id'] != subnet['vpc_id']:
        msg = _('Route table %(rtb_id)s and subnet %(subnet_id)s belong to '
                'different networks')
        msg = msg % {'rtb_id': route_table_id,
                     'subnet_id': subnet_id}
        raise exception.InvalidParameterValue(msg)
    if 'route_table_id' in subnet:
        msg = _('The specified association for route table %(rtb_id)s '
                'conflicts with an existing association')
        msg = msg % {'rtb_id': route_table_id}
        raise exception.ResourceAlreadyAssociated(msg)

    with common.OnCrashCleaner() as cleaner:
        _associate_subnet_item(context, subnet, route_table['id'])
        cleaner.addCleanup(_disassociate_subnet_item, context, subnet)

        _update_subnet_routes(context, cleaner, subnet, route_table)

    return {'associationId': ec2utils.change_ec2_id_kind(subnet['id'],
                                                         'rtbassoc')}
 def test_detach_network_interface(self):
     network_interface = tools.update_dict(fakes.DB_NETWORK_INTERFACE_2,
                                           {'device_index': 1})
     self.set_mock_db_items(network_interface)
     self.neutron.show_port.return_value = ({'port': fakes.OS_PORT_2})
     self.execute(
         'DetachNetworkInterface', {
             'AttachmentId':
             ec2utils.change_ec2_id_kind(fakes.ID_EC2_NETWORK_INTERFACE_2,
                                         'eni-attach')
         })
     self.neutron.update_port.assert_called_once_with(
         fakes.ID_OS_PORT_2,
         {'port': {
             'device_id': '',
             'device_owner': ''
         }})
     self.db_api.update_item.assert_called_once_with(
         mock.ANY,
         tools.purge_dict(
             fakes.DB_NETWORK_INTERFACE_2, {
                 'device_index', 'instance_id', 'delete_on_termination',
                 'attach_time'
             }))
Example #31
0
def _create_security_group(context, group_name, group_description,
                           vpc_id=None, default=False):
    nova = clients.nova(context)
    with common.OnCrashCleaner() as cleaner:
        try:
            os_security_group = nova.security_groups.create(group_name,
                                                            group_description)
        except nova_exception.OverLimit:
            raise exception.ResourceLimitExceeded(resource='security groups')
        cleaner.addCleanup(nova.security_groups.delete,
                           os_security_group.id)
        if vpc_id:
            # NOTE(Alex) Check if such vpc exists
            ec2utils.get_db_item(context, vpc_id)
        item = {'vpc_id': vpc_id, 'os_id': os_security_group.id}
        if not default:
            security_group = db_api.add_item(context, 'sg', item)
        else:
            item['id'] = ec2utils.change_ec2_id_kind(vpc_id, 'sg')
            # NOTE(andrey-mp): try to add item with specific id
            # and catch exception if it exists
            security_group = db_api.restore_item(context, 'sg', item)
        return {'return': 'true',
                'groupId': security_group['id']}
Example #32
0
def _format_route_table(context, route_table, is_main=False,
                        associated_subnet_ids=[],
                        gateways={},
                        network_interfaces={},
                        vpn_connections_by_gateway_id={}):
    vpc_id = route_table['vpc_id']
    ec2_route_table = {
        'routeTableId': route_table['id'],
        'vpcId': vpc_id,
        'routeSet': [],
        'propagatingVgwSet': [
            {'gatewayId': vgw_id}
            for vgw_id in route_table.get('propagating_gateways', [])],
        # NOTE(ft): AWS returns empty tag set for a route table
        # if no tag exists
        'tagSet': [],
    }
    # TODO(ft): refactor to get Nova instances outside of this function
    nova = clients.nova(context)
    for route in route_table['routes']:
        origin = ('CreateRouteTable'
                  if route.get('gateway_id', 0) is None else
                  'CreateRoute')
        ec2_route = {'destinationCidrBlock': route['destination_cidr_block'],
                     'origin': origin}
        if 'gateway_id' in route:
            gateway_id = route['gateway_id']
            if gateway_id is None:
                state = 'active'
                ec2_gateway_id = 'local'
            else:
                gateway = gateways.get(gateway_id)
                state = ('active'
                         if gateway and gateway.get('vpc_id') == vpc_id else
                         'blackhole')
                ec2_gateway_id = gateway_id
            ec2_route.update({'gatewayId': ec2_gateway_id,
                              'state': state})
        else:
            network_interface_id = route['network_interface_id']
            network_interface = network_interfaces.get(network_interface_id)
            instance_id = (network_interface.get('instance_id')
                           if network_interface else
                           None)
            state = 'blackhole'
            if instance_id:
                instance = db_api.get_item_by_id(context, instance_id)
                if instance:
                    try:
                        os_instance = nova.servers.get(instance['os_id'])
                        if os_instance and os_instance.status == 'ACTIVE':
                            state = 'active'
                    except nova_exception.NotFound:
                        pass
                ec2_route.update({'instanceId': instance_id,
                                  'instanceOwnerId': context.project_id})
            ec2_route.update({'networkInterfaceId': network_interface_id,
                              'state': state})
        ec2_route_table['routeSet'].append(ec2_route)

    for vgw_id in route_table.get('propagating_gateways', []):
        vgw = gateways.get(vgw_id)
        if vgw and vgw_id in vpn_connections_by_gateway_id:
            cidrs = set()
            vpn_connections = vpn_connections_by_gateway_id[vgw_id]
            for vpn_connection in vpn_connections:
                cidrs.update(vpn_connection['cidrs'])
            state = 'active' if vgw['vpc_id'] == vpc_id else 'blackhole'
            for cidr in cidrs:
                ec2_route = {'gatewayId': vgw_id,
                             'destinationCidrBlock': cidr,
                             'state': state,
                             'origin': 'EnableVgwRoutePropagation'}
                ec2_route_table['routeSet'].append(ec2_route)

    associations = []
    if is_main:
        associations.append({
            'routeTableAssociationId': ec2utils.change_ec2_id_kind(vpc_id,
                                                                   'rtbassoc'),
            'routeTableId': route_table['id'],
            'main': True})
    for subnet_id in associated_subnet_ids:
        associations.append({
            'routeTableAssociationId': ec2utils.change_ec2_id_kind(subnet_id,
                                                                   'rtbassoc'),
            'routeTableId': route_table['id'],
            'subnetId': subnet_id,
            'main': False})
    if associations:
        ec2_route_table['associationSet'] = associations

    return ec2_route_table
def _format_network_interface(context, network_interface, os_port,
                              associated_ec2_addresses=[], security_groups={}):
    ec2_network_interface = {}
    ec2_network_interface['networkInterfaceId'] = network_interface['id']
    ec2_network_interface['subnetId'] = network_interface['subnet_id']
    ec2_network_interface['vpcId'] = network_interface['vpc_id']
    ec2_network_interface['description'] = network_interface['description']
    ec2_network_interface['sourceDestCheck'] = (
        network_interface.get('source_dest_check', True))
    ec2_network_interface['requesterManaged'] = (
        os_port.get('device_owner', '').startswith('network:'))
    ec2_network_interface['ownerId'] = context.project_id
    security_group_set = []
    for sg_id in os_port['security_groups']:
        if security_groups.get(sg_id):
            security_group_set.append(security_groups[sg_id])
    ec2_network_interface['groupSet'] = security_group_set
    if 'instance_id' in network_interface:
        ec2_network_interface['status'] = 'in-use'
        ec2_network_interface['attachment'] = {
            'attachmentId': ec2utils.change_ec2_id_kind(
                    network_interface['id'], 'eni-attach'),
            'instanceId': network_interface['instance_id'],
            'deviceIndex': network_interface['device_index'],
            'status': 'attached',
            'deleteOnTermination': network_interface['delete_on_termination'],
            'attachTime': network_interface['attach_time'],
            'instanceOwnerId': context.project_id
        }
    else:
        ec2_network_interface['status'] = 'available'
    ec2_network_interface['macAddress'] = os_port['mac_address']
    if os_port['fixed_ips']:
        ipsSet = []
        for ip in os_port['fixed_ips']:
            primary = (
                network_interface.get('private_ip_address', '') ==
                ip['ip_address'])
            item = {'privateIpAddress': ip['ip_address'],
                    'primary': primary}
            ec2_address = next(
                (addr for addr in associated_ec2_addresses
                 if addr['privateIpAddress'] == ip['ip_address']),
                None)
            if ec2_address:
                item['association'] = {
                    'associationId': ec2utils.change_ec2_id_kind(
                                    ec2_address['allocationId'], 'eipassoc'),
                    'allocationId': ec2_address['allocationId'],
                    'ipOwnerId': context.project_id,
                    'publicDnsName': None,
                    'publicIp': ec2_address['publicIp'],
                }
            if primary:
                ipsSet.insert(0, item)
            else:
                ipsSet.append(item)
        ec2_network_interface['privateIpAddressesSet'] = ipsSet
        primary_ip = ipsSet[0]
        ec2_network_interface['privateIpAddress'] = (
            primary_ip['privateIpAddress'])
        if 'association' in primary_ip:
            ec2_network_interface['association'] = primary_ip['association']
    # NOTE(ft): AWS returns empty tag set for a network interface
    # if no tag exists
    ec2_network_interface['tagSet'] = []
    return ec2_network_interface
Example #34
0
    def associate_address(self, context, public_ip=None, instance_id=None,
                          allocation_id=None, network_interface_id=None,
                          private_ip_address=None, allow_reassociation=False):
        instance_network_interfaces = []
        if instance_id:
            # TODO(ft): implement search in DB layer
            for eni in db_api.get_items(context, 'eni'):
                if eni.get('instance_id') == instance_id:
                    instance_network_interfaces.append(eni)

        neutron = clients.neutron(context)

        if public_ip:
            # TODO(ft): implement search in DB layer
            address = next((addr for addr in db_api.get_items(context,
                                                              'eipalloc')
                            if addr['public_ip'] == public_ip), None)

            if not CONF.disable_ec2_classic:
                if instance_network_interfaces:
                    msg = _('You must specify an allocation id when mapping '
                            'an address to a VPC instance')
                    raise exception.InvalidParameterCombination(msg)
                if address and _is_address_valid(context, neutron, address):
                    msg = _(
                        "The address '%(public_ip)s' does not belong to you.")
                    raise exception.AuthFailure(msg % {'public_ip': public_ip})

                os_instance_id = ec2utils.get_db_item(context,
                                                      instance_id)['os_id']
                # NOTE(ft): check the public IP exists to raise AWS exception
                # otherwise
                self.get_os_floating_ip_by_public_ip(context, public_ip)
                nova = clients.nova(context)
                nova.servers.add_floating_ip(os_instance_id, public_ip)
                return None

            if not address:
                msg = _("The address '%(public_ip)s' does not belong to you.")
                raise exception.AuthFailure(msg % {'public_ip': public_ip})
            allocation_id = address['id']

        if instance_id:
            if not instance_network_interfaces:
                # NOTE(ft): check the instance exists
                ec2utils.get_db_item(context, instance_id)
                msg = _('You must specify an IP address when mapping '
                        'to a non-VPC instance')
                raise exception.InvalidParameterCombination(msg)
            if len(instance_network_interfaces) > 1:
                raise exception.InvalidInstanceId(instance_id=instance_id)
            network_interface = instance_network_interfaces[0]
        else:
            network_interface = ec2utils.get_db_item(context,
                                                     network_interface_id)
        if not private_ip_address:
            private_ip_address = network_interface['private_ip_address']

        address = ec2utils.get_db_item(context, allocation_id)
        if not _is_address_valid(context, neutron, address):
            raise exception.InvalidAllocationIDNotFound(
                id=allocation_id)

        if address.get('network_interface_id') == network_interface['id']:
            # NOTE(ft): idempotent call
            pass
        elif address.get('network_interface_id') and not allow_reassociation:
            msg = _('resource %(eipalloc_id)s is already associated with '
                    'associate-id %(eipassoc_id)s')
            msg = msg % {'eipalloc_id': allocation_id,
                         'eipassoc_id': ec2utils.change_ec2_id_kind(
                                                address['id'], 'eipassoc')}
            raise exception.ResourceAlreadyAssociated(msg)
        else:
            internet_gateways = (
                internet_gateway_api.describe_internet_gateways(
                    context,
                    filter=[{'name': 'attachment.vpc-id',
                             'value': [network_interface['vpc_id']]}])
                ['internetGatewaySet'])
            if len(internet_gateways) == 0:
                msg = _('Network %(vpc_id)s is not attached to any internet '
                        'gateway') % {'vpc_id': network_interface['vpc_id']}
                raise exception.GatewayNotAttached(msg)

            with common.OnCrashCleaner() as cleaner:
                _associate_address_item(context, address,
                                        network_interface['id'],
                                        private_ip_address)
                cleaner.addCleanup(_disassociate_address_item, context,
                                   address)

                os_floating_ip = {'port_id': network_interface['os_id'],
                                  'fixed_ip_address': private_ip_address}
                neutron.update_floatingip(address['os_id'],
                                          {'floatingip': os_floating_ip})
        # TODO(ft): generate unique association id for each act of association
        return ec2utils.change_ec2_id_kind(address['id'], 'eipassoc')
Example #35
0
def _format_network_interface(context,
                              network_interface,
                              os_port,
                              associated_ec2_addresses=[],
                              security_groups={}):
    ec2_network_interface = {}
    ec2_network_interface['networkInterfaceId'] = network_interface['id']
    ec2_network_interface['subnetId'] = network_interface['subnet_id']
    ec2_network_interface['vpcId'] = network_interface['vpc_id']
    ec2_network_interface['description'] = network_interface['description']
    ec2_network_interface['sourceDestCheck'] = (network_interface.get(
        'source_dest_check', True))
    ec2_network_interface['requesterManaged'] = (os_port.get(
        'device_owner', '').startswith('network:'))
    ec2_network_interface['ownerId'] = context.project_id
    security_group_set = []
    for sg_id in os_port['security_groups']:
        if security_groups.get(sg_id):
            security_group_set.append(security_groups[sg_id])
    ec2_network_interface['groupSet'] = security_group_set
    if 'instance_id' in network_interface:
        ec2_network_interface['status'] = 'in-use'
        ec2_network_interface['attachment'] = {
            'attachmentId':
            ec2utils.change_ec2_id_kind(network_interface['id'], 'eni-attach'),
            'instanceId':
            network_interface['instance_id'],
            'deviceIndex':
            network_interface['device_index'],
            'status':
            'attached',
            'deleteOnTermination':
            network_interface['delete_on_termination'],
            'attachTime':
            network_interface['attach_time'],
            'instanceOwnerId':
            context.project_id
        }
    else:
        ec2_network_interface['status'] = 'available'
    ec2_network_interface['macAddress'] = os_port['mac_address']
    if os_port['fixed_ips']:
        ipsSet = []
        for ip in os_port['fixed_ips']:
            primary = (network_interface.get('private_ip_address',
                                             '') == ip['ip_address'])
            item = {'privateIpAddress': ip['ip_address'], 'primary': primary}
            ec2_address = next(
                (addr for addr in associated_ec2_addresses
                 if addr['privateIpAddress'] == ip['ip_address']), None)
            if ec2_address:
                item['association'] = {
                    'associationId':
                    ec2utils.change_ec2_id_kind(ec2_address['allocationId'],
                                                'eipassoc'),
                    'allocationId':
                    ec2_address['allocationId'],
                    'ipOwnerId':
                    context.project_id,
                    'publicDnsName':
                    None,
                    'publicIp':
                    ec2_address['publicIp'],
                }
            if primary:
                ipsSet.insert(0, item)
            else:
                ipsSet.append(item)
        ec2_network_interface['privateIpAddressesSet'] = ipsSet
        primary_ip = ipsSet[0]
        ec2_network_interface['privateIpAddress'] = (
            primary_ip['privateIpAddress'])
        if 'association' in primary_ip:
            ec2_network_interface['association'] = primary_ip['association']
    # NOTE(ft): AWS returns empty tag set for a network interface
    # if no tag exists
    ec2_network_interface['tagSet'] = []
    return ec2_network_interface
Example #36
0
    def associate_address(self,
                          context,
                          public_ip=None,
                          instance_id=None,
                          allocation_id=None,
                          network_interface_id=None,
                          private_ip_address=None,
                          allow_reassociation=False):
        instance_network_interfaces = []
        if instance_id:
            # TODO(ft): implement search in DB layer
            for eni in db_api.get_items(context, 'eni'):
                if instance_id and eni.get('instance_id') == instance_id:
                    instance_network_interfaces.append(eni)

        neutron = clients.neutron(context)
        if public_ip:
            if instance_network_interfaces:
                msg = _('You must specify an allocation id when mapping '
                        'an address to a VPC instance')
                raise exception.InvalidParameterCombination(msg)
            # TODO(ft): implement search in DB layer
            address = next((addr
                            for addr in db_api.get_items(context, 'eipalloc')
                            if addr['public_ip'] == public_ip), None)
            if address and _is_address_valid(context, neutron, address):
                msg = _("The address '%(public_ip)s' does not belong to you.")
                raise exception.AuthFailure(msg % {'public_ip': public_ip})

            # NOTE(ft): in fact only the first two parameters are used to
            # associate an address in EC2 Classic mode. Other parameters are
            # sent to validate their emptiness in one place
            return AddressEngineNova().associate_address(
                context,
                public_ip=public_ip,
                instance_id=instance_id,
                allocation_id=allocation_id,
                network_interface_id=network_interface_id,
                private_ip_address=private_ip_address,
                allow_reassociation=allow_reassociation)

        if instance_id:
            if not instance_network_interfaces:
                # NOTE(ft): check the instance exists
                ec2utils.get_db_item(context, instance_id)
                msg = _('You must specify an IP address when mapping '
                        'to a non-VPC instance')
                raise exception.InvalidParameterCombination(msg)
            if len(instance_network_interfaces) > 1:
                raise exception.InvalidInstanceId(instance_id=instance_id)
            network_interface = instance_network_interfaces[0]
        else:
            network_interface = ec2utils.get_db_item(context,
                                                     network_interface_id)
        if not private_ip_address:
            private_ip_address = network_interface['private_ip_address']

        address = ec2utils.get_db_item(context, allocation_id)
        if not _is_address_valid(context, neutron, address):
            raise exception.InvalidAllocationIDNotFound(id=allocation_id)

        if address.get('network_interface_id') == network_interface['id']:
            # NOTE(ft): idempotent call
            pass
        elif address.get('network_interface_id') and not allow_reassociation:
            msg = _('resource %(eipalloc_id)s is already associated with '
                    'associate-id %(eipassoc_id)s')
            msg = msg % {
                'eipalloc_id':
                allocation_id,
                'eipassoc_id':
                ec2utils.change_ec2_id_kind(address['id'], 'eipassoc')
            }
            raise exception.ResourceAlreadyAssociated(msg)
        else:
            internet_gateways = (
                internet_gateway_api.describe_internet_gateways(
                    context,
                    filter=[{
                        'name': 'attachment.vpc-id',
                        'value': [network_interface['vpc_id']]
                    }])['internetGatewaySet'])
            if len(internet_gateways) == 0:
                msg = _('Network %(vpc_id)s is not attached to any internet '
                        'gateway') % {
                            'vpc_id': network_interface['vpc_id']
                        }
                raise exception.GatewayNotAttached(msg)

            with common.OnCrashCleaner() as cleaner:
                _associate_address_item(context, address,
                                        network_interface['id'],
                                        private_ip_address)
                cleaner.addCleanup(_disassociate_address_item, context,
                                   address)

                os_floating_ip = {
                    'port_id': network_interface['os_id'],
                    'fixed_ip_address': private_ip_address
                }
                neutron.update_floatingip(address['os_id'],
                                          {'floatingip': os_floating_ip})
        # TODO(ft): generate unique association id for each act of association
        return ec2utils.change_ec2_id_kind(address['id'], 'eipassoc')
Example #37
0
def _format_route_table(context, route_table, is_main=False,
                        associated_subnet_ids=[],
                        gateways={},
                        network_interfaces={},
                        vpn_connections_by_gateway_id={}):
    vpc_id = route_table['vpc_id']
    ec2_route_table = {
        'routeTableId': route_table['id'],
        'vpcId': vpc_id,
        'routeSet': [],
        'propagatingVgwSet': [
            {'gatewayId': vgw_id}
            for vgw_id in route_table.get('propagating_gateways', [])],
        # NOTE(ft): AWS returns empty tag set for a route table
        # if no tag exists
        'tagSet': [],
    }
    # TODO(ft): refactor to get Nova instances outside of this function
    nova = clients.nova(context)
    for route in route_table['routes']:
        origin = ('CreateRouteTable'
                  if route.get('gateway_id', 0) is None else
                  'CreateRoute')
        ec2_route = {'destinationCidrBlock': route['destination_cidr_block'],
                     'origin': origin}
        if 'gateway_id' in route:
            gateway_id = route['gateway_id']
            if gateway_id is None:
                state = 'active'
                ec2_gateway_id = 'local'
            else:
                gateway = gateways.get(gateway_id)
                state = ('active'
                         if gateway and gateway.get('vpc_id') == vpc_id else
                         'blackhole')
                ec2_gateway_id = gateway_id
            ec2_route.update({'gatewayId': ec2_gateway_id,
                              'state': state})
        else:
            network_interface_id = route['network_interface_id']
            network_interface = network_interfaces.get(network_interface_id)
            instance_id = (network_interface.get('instance_id')
                           if network_interface else
                           None)
            state = 'blackhole'
            if instance_id:
                instance = db_api.get_item_by_id(context, instance_id)
                if instance:
                    try:
                        os_instance = nova.servers.get(instance['os_id'])
                        if os_instance and os_instance.status == 'ACTIVE':
                            state = 'active'
                    except nova_exception.NotFound:
                        pass
                ec2_route.update({'instanceId': instance_id,
                                  'instanceOwnerId': context.project_id})
            ec2_route.update({'networkInterfaceId': network_interface_id,
                              'state': state})
        ec2_route_table['routeSet'].append(ec2_route)

    for vgw_id in route_table.get('propagating_gateways', []):
        vgw = gateways.get(vgw_id)
        if vgw and vgw_id in vpn_connections_by_gateway_id:
            cidrs = set()
            vpn_connections = vpn_connections_by_gateway_id[vgw_id]
            for vpn_connection in vpn_connections:
                cidrs.update(vpn_connection['cidrs'])
            state = 'active' if vgw['vpc_id'] == vpc_id else 'blackhole'
            for cidr in cidrs:
                ec2_route = {'gatewayId': vgw_id,
                             'destinationCidrBlock': cidr,
                             'state': state,
                             'origin': 'EnableVgwRoutePropagation'}
                ec2_route_table['routeSet'].append(ec2_route)

    associations = []
    if is_main:
        associations.append({
            'routeTableAssociationId': ec2utils.change_ec2_id_kind(vpc_id,
                                                                   'rtbassoc'),
            'routeTableId': route_table['id'],
            'main': True})
    for subnet_id in associated_subnet_ids:
        associations.append({
            'routeTableAssociationId': ec2utils.change_ec2_id_kind(subnet_id,
                                                                   'rtbassoc'),
            'routeTableId': route_table['id'],
            'subnetId': subnet_id,
            'main': False})
    if associations:
        ec2_route_table['associationSet'] = associations

    return ec2_route_table