def attach_internet_gateway(context, internet_gateway_id, vpc_id): igw = ec2utils.get_db_item(context, internet_gateway_id) if igw.get('vpc_id'): msg_params = {'igw_id': igw['id'], 'vpc_id': igw['vpc_id']} msg = _("resource %(igw_id)s is already attached to " "network %(vpc_id)s") % msg_params raise exception.ResourceAlreadyAssociated(msg) vpc = ec2utils.get_db_item(context, vpc_id) # TODO(ft): move search by vpc_id to DB api for gw in db_api.get_items(context, 'igw'): if gw.get('vpc_id') == vpc['id']: msg = _("Network %(vpc_id)s already has an internet gateway " "attached") % { 'vpc_id': vpc['id'] } raise exception.InvalidParameterValue(msg) os_public_network = ec2utils.get_os_public_network(context) neutron = clients.neutron(context) # TODO(ft): set attaching state into db with common.OnCrashCleaner() as cleaner: _attach_internet_gateway_item(context, igw, vpc['id']) cleaner.addCleanup(_detach_internet_gateway_item, context, igw) neutron.add_gateway_router(vpc['os_id'], {'network_id': os_public_network['id']}) return True
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) return AddressEngineNova().release_address(context, public_ip, None) 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: 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
def detach_vpn_gateway(context, vpc_id, vpn_gateway_id): vpn_gateway = ec2utils.get_db_item(context, vpn_gateway_id) if vpn_gateway['vpc_id'] != vpc_id: raise exception.InvalidVpnGatewayAttachmentNotFound( vgw_id=vpn_gateway_id, vpc_id=vpc_id) vpc = db_api.get_item_by_id(context, vpc_id) neutron = clients.neutron(context) remove_os_gateway_router = ( ec2utils.get_attached_gateway(context, vpc_id, 'igw') is None) subnets = [subnet for subnet in db_api.get_items(context, 'subnet') if subnet['vpc_id'] == vpc['id']] with common.OnCrashCleaner() as cleaner: _detach_vpn_gateway_item(context, vpn_gateway) cleaner.addCleanup(_attach_vpn_gateway_item, context, vpn_gateway, vpc_id) vpn_connection_api._stop_gateway_vpn_connections( context, neutron, cleaner, vpn_gateway) for subnet in subnets: _delete_subnet_vpnservice(context, neutron, cleaner, subnet) if remove_os_gateway_router: try: neutron.remove_gateway_router(vpc['os_id']) except neutron_exception.NotFound: pass return True
def attach_internet_gateway(context, internet_gateway_id, vpc_id): igw = ec2utils.get_db_item(context, internet_gateway_id) if igw.get('vpc_id'): msg_params = {'igw_id': igw['id'], 'vpc_id': igw['vpc_id']} msg = _('resource %(igw_id)s is already attached to ' 'network %(vpc_id)s') % msg_params raise exception.ResourceAlreadyAssociated(msg) vpc = ec2utils.get_db_item(context, vpc_id) if ec2utils.get_attached_gateway(context, vpc['id'], 'igw'): msg = _('Network %(vpc_id)s already has an internet gateway ' 'attached') % { 'vpc_id': vpc['id'] } raise exception.InvalidParameterValue(msg) external_network_id = None if not ec2utils.get_attached_gateway(context, vpc['id'], 'vgw'): external_network_id = ec2utils.get_os_public_network(context)['id'] neutron = clients.neutron(context) # TODO(ft): set attaching state into db with common.OnCrashCleaner() as cleaner: _attach_internet_gateway_item(context, igw, vpc['id']) cleaner.addCleanup(_detach_internet_gateway_item, context, igw) if external_network_id: neutron.add_gateway_router(vpc['os_id'], {'network_id': external_network_id}) return True
def delete_vpn_connection(context, vpn_connection_id): vpn_connection = ec2utils.get_db_item(context, vpn_connection_id) with common.OnCrashCleaner() as cleaner: db_api.delete_item(context, vpn_connection['id']) cleaner.addCleanup(db_api.restore_item, context, 'vpn', vpn_connection) neutron = clients.neutron(context) _stop_vpn_connection(neutron, vpn_connection) try: neutron.delete_ipsecpolicy(vpn_connection['os_ipsecpolicy_id']) except neutron_exception.Conflict as ex: LOG.warning( _('Failed to delete ipsecoplicy %(os_id)s during deleting ' 'VPN connection %(id)s. Reason: %(reason)s'), { 'id': vpn_connection['id'], 'os_id': vpn_connection['os_ipsecpolicy_id'], 'reason': ex.message }) except neutron_exception.NotFound: pass try: neutron.delete_ikepolicy(vpn_connection['os_ikepolicy_id']) except neutron_exception.Conflict as ex: LOG.warning( _('Failed to delete ikepolicy %(os_id)s during deleting ' 'VPN connection %(id)s. Reason: %(reason)s'), { 'id': vpn_connection['id'], 'os_id': vpn_connection['os_ikepolicy_id'], 'reason': ex.message }) except neutron_exception.NotFound: pass return True
def associate_dhcp_options(context, dhcp_options_id, vpc_id): vpc = ec2utils.get_db_item(context, vpc_id) rollback_dhcp_options_id = vpc.get('dhcp_options_id') if dhcp_options_id == 'default': dhcp_options_id = None dhcp_options = None else: dhcp_options = ec2utils.get_db_item(context, dhcp_options_id) dhcp_options_id = dhcp_options['id'] neutron = clients.neutron(context) os_ports = neutron.list_ports(tenant_id=context.project_id)['ports'] network_interfaces = db_api.get_items(context, 'eni') rollback_dhcp_options_object = ( db_api.get_item_by_id(context, rollback_dhcp_options_id) if dhcp_options_id is not None else None) with common.OnCrashCleaner() as cleaner: _associate_vpc_item(context, vpc, dhcp_options_id) cleaner.addCleanup(_associate_vpc_item, context, vpc, rollback_dhcp_options_id) for network_interface in network_interfaces: os_port = next((p for p in os_ports if p['id'] == network_interface['os_id']), None) if not os_port: continue _add_dhcp_opts_to_port(context, dhcp_options, network_interface, os_port, neutron) cleaner.addCleanup(_add_dhcp_opts_to_port, context, rollback_dhcp_options_object, network_interface, os_port, neutron) return 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')}
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) return AddressEngineNova().release_address(context, public_ip, None) 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: 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
def delete_group(self, context, group_name=None, group_id=None, delete_default=False): neutron = clients.neutron(context) if group_id is None or not group_id.startswith('sg-'): return SecurityGroupEngineNova().delete_group(context, group_name, group_id) security_group = ec2utils.get_db_item(context, group_id) try: if not delete_default: os_security_group = neutron.show_security_group( security_group['os_id']) if (os_security_group and os_security_group['security_group']['name'] == security_group['vpc_id']): raise exception.CannotDelete() neutron.delete_security_group(security_group['os_id']) except neutron_exception.Conflict as ex: # TODO(Alex): Instance ID is unknown here, report exception message # in its place - looks readable. raise exception.DependencyViolation( obj1_id=group_id, obj2_id=ex.message) except neutron_exception.NeutronClientException as ex: # TODO(Alex): do log error # TODO(Alex): adjust caught exception classes to catch: # the port doesn't exist pass db_api.delete_item(context, group_id)
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}})
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 }})
def associate_dhcp_options(context, dhcp_options_id, vpc_id): vpc = ec2utils.get_db_item(context, vpc_id) rollback_dhcp_options_id = vpc.get('dhcp_options_id') if dhcp_options_id == 'default': dhcp_options_id = None dhcp_options = None else: dhcp_options = ec2utils.get_db_item(context, dhcp_options_id) dhcp_options_id = dhcp_options['id'] neutron = clients.neutron(context) os_ports = neutron.list_ports(tenant_id=context.project_id)['ports'] network_interfaces = db_api.get_items(context, 'eni') rollback_dhcp_options_object = (db_api.get_item_by_id( context, rollback_dhcp_options_id) if dhcp_options_id is not None else None) with common.OnCrashCleaner() as cleaner: _associate_vpc_item(context, vpc, dhcp_options_id) cleaner.addCleanup(_associate_vpc_item, context, vpc, rollback_dhcp_options_id) for network_interface in network_interfaces: os_port = next( (p for p in os_ports if p['id'] == network_interface['os_id']), None) if not os_port: continue _add_dhcp_opts_to_port(context, dhcp_options, network_interface, os_port, neutron) cleaner.addCleanup(_add_dhcp_opts_to_port, context, rollback_dhcp_options_object, network_interface, os_port, neutron) return True
def attach_vpn_gateway(context, vpc_id, vpn_gateway_id): vpn_gateway = ec2utils.get_db_item(context, vpn_gateway_id) vpc = ec2utils.get_db_item(context, vpc_id) if vpn_gateway['vpc_id'] and vpn_gateway['vpc_id'] != vpc['id']: raise exception.VpnGatewayAttachmentLimitExceeded() attached_vgw = ec2utils.get_attached_gateway(context, vpc['id'], 'vgw') if attached_vgw and attached_vgw['id'] != vpn_gateway['id']: raise exception.InvalidVpcState(vpc_id=vpc['id'], vgw_id=attached_vgw['id']) subnets = [subnet for subnet in db_api.get_items(context, 'subnet') if subnet['vpc_id'] == vpc['id']] if not vpn_gateway['vpc_id']: external_network_id = None if not ec2utils.get_attached_gateway(context, vpc['id'], 'igw'): external_network_id = ec2utils.get_os_public_network(context)['id'] neutron = clients.neutron(context) with common.OnCrashCleaner() as cleaner: _attach_vpn_gateway_item(context, vpn_gateway, vpc['id']) cleaner.addCleanup(_detach_vpn_gateway_item, context, vpn_gateway) if external_network_id: neutron.add_gateway_router(vpc['os_id'], {'network_id': external_network_id}) cleaner.addCleanup(neutron.remove_gateway_router, vpc['os_id']) for subnet in subnets: _create_subnet_vpnservice(context, neutron, cleaner, subnet, vpc) vpn_connection_api._reset_vpn_connections( context, neutron, cleaner, vpn_gateway, subnets=subnets) return {'attachment': _format_attachment(vpn_gateway)}
def _update_routes_in_associated_subnets(context, route_table, cleaner, rollabck_route_table_object, is_main=None): if is_main is None: vpc = db_api.get_item_by_id(context, route_table['vpc_id']) is_main = vpc['route_table_id'] == route_table['id'] if is_main: appropriate_rtb_ids = (route_table['id'], None) else: appropriate_rtb_ids = (route_table['id'], ) router_objects = _get_router_objects(context, route_table) neutron = clients.neutron(context) for subnet in db_api.get_items(context, 'subnet'): if (subnet['vpc_id'] == route_table['vpc_id'] and subnet.get('route_table_id') in appropriate_rtb_ids): _update_subnet_host_routes( context, subnet, route_table, cleaner=cleaner, rollback_route_table_object=rollabck_route_table_object, router_objects=router_objects, neutron=neutron)
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 delete_group(self, context, group_name=None, group_id=None, delete_default=False): neutron = clients.neutron(context) if group_id is None or not group_id.startswith('sg-'): return SecurityGroupEngineNova().delete_group( context, group_name, group_id) security_group = ec2utils.get_db_item(context, group_id) try: if not delete_default: os_security_group = neutron.show_security_group( security_group['os_id']) if (os_security_group and os_security_group['security_group']['name'] == security_group['vpc_id']): raise exception.CannotDelete() neutron.delete_security_group(security_group['os_id']) except neutron_exception.Conflict as ex: # TODO(Alex): Instance ID is unknown here, report exception message # in its place - looks readable. raise exception.DependencyViolation(obj1_id=group_id, obj2_id=ex.message) except neutron_exception.NeutronClientException as ex: # TODO(Alex): do log error # TODO(Alex): adjust caught exception classes to catch: # the port doesn't exist pass db_api.delete_item(context, group_id)
def unassign_private_ip_addresses(context, network_interface_id, private_ip_address): network_interface = ec2utils.get_db_item(context, network_interface_id) if network_interface['private_ip_address'] in private_ip_address: raise exception.InvalidParameterValue( value=str(network_interface['private_ip_address']), parameter='PrivateIpAddresses', reason='Primary IP address cannot be unassigned') neutron = clients.neutron(context) os_port = neutron.show_port(network_interface['os_id'])['port'] fixed_ips = os_port['fixed_ips'] or [] new_fixed_ips = [ ip for ip in fixed_ips if ip['ip_address'] not in private_ip_address ] if len(new_fixed_ips) + len(private_ip_address) != len(fixed_ips): msg = _('Some of the specified addresses are not assigned to ' 'interface %(id)s') % { 'id': network_interface_id } raise exception.InvalidParameterValue(msg) os_port = neutron.update_port(os_port['id'], {'port': { 'fixed_ips': new_fixed_ips }}) return True
def _update_routes_in_associated_subnets(context, cleaner, route_table, default_associations_only=None, update_target=None): if default_associations_only: appropriate_rtb_ids = (None, ) else: vpc = db_api.get_item_by_id(context, route_table['vpc_id']) if vpc['route_table_id'] == route_table['id']: appropriate_rtb_ids = (route_table['id'], None) else: appropriate_rtb_ids = (route_table['id'], ) neutron = clients.neutron(context) subnets = [ subnet for subnet in db_api.get_items(context, 'subnet') if (subnet['vpc_id'] == route_table['vpc_id'] and subnet.get('route_table_id') in appropriate_rtb_ids) ] # NOTE(ft): we need to update host routes for both host and vpn target # because vpn-related routes are present in host routes as well _update_host_routes(context, neutron, cleaner, route_table, subnets) if not update_target or update_target == VPN_TARGET: vpn_connection_api._update_vpn_routes(context, neutron, cleaner, route_table, subnets)
def delete_vpn_connection(context, vpn_connection_id): vpn_connection = ec2utils.get_db_item(context, vpn_connection_id) with common.OnCrashCleaner() as cleaner: db_api.delete_item(context, vpn_connection['id']) cleaner.addCleanup(db_api.restore_item, context, 'vpn', vpn_connection) neutron = clients.neutron(context) _stop_vpn_connection(neutron, vpn_connection) try: neutron.delete_ipsecpolicy(vpn_connection['os_ipsecpolicy_id']) except neutron_exception.Conflict as ex: LOG.warning( _('Failed to delete ipsecoplicy %(os_id)s during deleting ' 'VPN connection %(id)s. Reason: %(reason)s'), {'id': vpn_connection['id'], 'os_id': vpn_connection['os_ipsecpolicy_id'], 'reason': ex.message}) except neutron_exception.NotFound: pass try: neutron.delete_ikepolicy(vpn_connection['os_ikepolicy_id']) except neutron_exception.Conflict as ex: LOG.warning( _('Failed to delete ikepolicy %(os_id)s during deleting ' 'VPN connection %(id)s. Reason: %(reason)s'), {'id': vpn_connection['id'], 'os_id': vpn_connection['os_ikepolicy_id'], 'reason': ex.message}) except neutron_exception.NotFound: pass return True
def get_os_items(self): neutron = clients.neutron(self.context) self.os_networks = neutron.list_networks( tenant_id=self.context.project_id)['networks'] self.os_ports = neutron.list_ports( tenant_id=self.context.project_id)['ports'] return neutron.list_subnets( tenant_id=self.context.project_id)['subnets']
def authorize_security_group(self, context, rule_body): neutron = clients.neutron(context) try: os_security_group_rule = neutron.create_security_group_rule( {'security_group_rule': rule_body})['security_group_rule'] except neutron_exception.OverQuotaClient: raise exception.RulesPerSecurityGroupLimitExceeded() except neutron_exception.Conflict as ex: raise exception.InvalidPermissionDuplicate()
def delete_vpc(context, vpc_id): vpc = ec2utils.get_db_item(context, vpc_id) subnets = subnet_api.describe_subnets(context, filter=[{ 'name': 'vpc-id', 'value': [vpc_id] }])['subnetSet'] internet_gateways = internet_gateway_api.describe_internet_gateways( context, filter=[{ 'name': 'attachment.vpc-id', 'value': [vpc['id']] }])['internetGatewaySet'] route_tables = route_table_api.describe_route_tables(context, filter=[{ 'name': 'vpc-id', 'value': [vpc['id']] }])['routeTableSet'] security_groups = security_group_api.describe_security_groups( context, filter=[{ 'name': 'vpc-id', 'value': [vpc['id']] }])['securityGroupInfo'] if (subnets or internet_gateways or len(route_tables) > 1 or len(security_groups) > 1): msg = _("The vpc '%(vpc_id)s' has dependencies and " "cannot be deleted.") msg = msg % {'vpc_id': vpc['id']} raise exception.DependencyViolation(msg) neutron = clients.neutron(context) with common.OnCrashCleaner() as cleaner: db_api.delete_item(context, vpc['id']) cleaner.addCleanup(db_api.restore_item, context, 'vpc', vpc) route_table_api._delete_route_table(context, vpc['route_table_id'], cleaner=cleaner) if len(security_groups) > 0: security_group_api.delete_security_group( context, group_id=security_groups[0]['groupId'], delete_default=True) try: neutron.delete_router(vpc['os_id']) except neutron_exception.Conflict as ex: LOG.warning( _('Failed to delete router %(os_id)s during deleting ' 'VPC %(id)s. Reason: %(reason)s'), { 'id': vpc['id'], 'os_id': vpc['os_id'], 'reason': ex.message }) except neutron_exception.NotFound: pass return True
def create_subnet(context, vpc_id, cidr_block, availability_zone=None): vpc = ec2utils.get_db_item(context, vpc_id) vpc_ipnet = netaddr.IPNetwork(vpc['cidr_block']) subnet_ipnet = netaddr.IPNetwork(cidr_block) if subnet_ipnet not in vpc_ipnet: raise exception.InvalidSubnetRange(cidr_block=cidr_block) gateway_ip = str(netaddr.IPAddress(subnet_ipnet.first + 1)) main_route_table = db_api.get_item_by_id(context, vpc['route_table_id']) host_routes = route_table_api._get_subnet_host_routes( context, main_route_table, gateway_ip) neutron = clients.neutron(context) with common.OnCrashCleaner() as cleaner: os_network_body = {'network': {}} try: os_network = neutron.create_network(os_network_body)['network'] cleaner.addCleanup(neutron.delete_network, os_network['id']) # NOTE(Alex): AWS takes 4 first addresses (.1 - .4) but for # OpenStack we decided not to support this as compatibility. os_subnet_body = { 'subnet': { 'network_id': os_network['id'], 'ip_version': '4', 'cidr': cidr_block, 'host_routes': host_routes } } os_subnet = neutron.create_subnet(os_subnet_body)['subnet'] cleaner.addCleanup(neutron.delete_subnet, os_subnet['id']) except neutron_exception.OverQuotaClient: raise exception.SubnetLimitExceeded() try: neutron.add_interface_router(vpc['os_id'], {'subnet_id': os_subnet['id']}) except neutron_exception.BadRequest: raise exception.InvalidSubnetConflict(cidr_block=cidr_block) cleaner.addCleanup(neutron.remove_interface_router, vpc['os_id'], {'subnet_id': os_subnet['id']}) subnet = db_api.add_item(context, 'subnet', { 'os_id': os_subnet['id'], 'vpc_id': vpc['id'] }) cleaner.addCleanup(db_api.delete_item, context, subnet['id']) neutron.update_network(os_network['id'], {'network': { 'name': subnet['id'] }}) neutron.update_subnet(os_subnet['id'], {'subnet': { 'name': subnet['id'] }}) os_ports = neutron.list_ports(tenant_id=context.project_id)['ports'] return { 'subnet': _format_subnet(context, subnet, os_subnet, os_network, os_ports) }
def test_neutron(self, neutron): context = mock.Mock( auth_token='fake_token', service_catalog=[{'type': 'network', 'endpoints': [{'publicURL': 'neutron_url'}]}]) res = clients.neutron(context) self.assertEqual(neutron.return_value, res) neutron.assert_called_with( auth_url='keystone_url', cacert=None, service_type='network', insecure=False, token='fake_token', endpoint_url='neutron_url')
def get_os_items(self): addresses = address_api.describe_addresses(self.context) self.ec2_addresses = collections.defaultdict(list) for address in addresses['addressesSet']: if 'networkInterfaceId' in address: self.ec2_addresses[ address['networkInterfaceId']].append(address) self.security_groups = ( security_group_api._format_security_groups_ids_names(self.context)) neutron = clients.neutron(self.context) return neutron.list_ports(tenant_id=self.context.project_id)['ports']
def get_os_items(self): addresses = address_api.describe_addresses(self.context) self.ec2_addresses = collections.defaultdict(list) for address in addresses['addressesSet']: if 'networkInterfaceId' in address: self.ec2_addresses[address['networkInterfaceId']].append( address) self.security_groups = ( security_group_api._format_security_groups_ids_names(self.context)) neutron = clients.neutron(self.context) return neutron.list_ports(tenant_id=self.context.project_id)['ports']
def create_subnet(context, vpc_id, cidr_block, availability_zone=None): vpc = ec2utils.get_db_item(context, vpc_id) vpc_ipnet = netaddr.IPNetwork(vpc['cidr_block']) subnet_ipnet = netaddr.IPNetwork(cidr_block) if subnet_ipnet not in vpc_ipnet: raise exception.InvalidSubnetRange(cidr_block=cidr_block) main_route_table = db_api.get_item_by_id(context, vpc['route_table_id']) (host_routes, gateway_ip) = route_table_api._get_subnet_host_routes_and_gateway_ip( context, main_route_table, cidr_block) neutron = clients.neutron(context) with common.OnCrashCleaner() as cleaner: os_network_body = {'network': {}} try: os_network = neutron.create_network(os_network_body)['network'] cleaner.addCleanup(neutron.delete_network, os_network['id']) # NOTE(Alex): AWS takes 4 first addresses (.1 - .4) but for # OpenStack we decided not to support this as compatibility. os_subnet_body = {'subnet': {'network_id': os_network['id'], 'ip_version': '4', 'cidr': cidr_block, 'host_routes': host_routes}} os_subnet = neutron.create_subnet(os_subnet_body)['subnet'] cleaner.addCleanup(neutron.delete_subnet, os_subnet['id']) except neutron_exception.OverQuotaClient: raise exception.SubnetLimitExceeded() try: neutron.add_interface_router(vpc['os_id'], {'subnet_id': os_subnet['id']}) except neutron_exception.BadRequest: raise exception.InvalidSubnetConflict(cidr_block=cidr_block) cleaner.addCleanup(neutron.remove_interface_router, vpc['os_id'], {'subnet_id': os_subnet['id']}) subnet = db_api.add_item(context, 'subnet', {'os_id': os_subnet['id'], 'vpc_id': vpc['id']}) cleaner.addCleanup(db_api.delete_item, context, subnet['id']) vpn_gateway_api._start_vpn_in_subnet(context, neutron, cleaner, subnet, vpc, main_route_table) neutron.update_network(os_network['id'], {'network': {'name': subnet['id']}}) # NOTE(ft): In some cases we need gateway_ip to be None (see # _get_subnet_host_routes_and_gateway_ip). It's not set during subnet # creation to allow automatic configuration of the default port by # which subnet is attached to the router. neutron.update_subnet(os_subnet['id'], {'subnet': {'name': subnet['id'], 'gateway_ip': gateway_ip}}) os_ports = neutron.list_ports(tenant_id=context.project_id)['ports'] return {'subnet': _format_subnet(context, subnet, os_subnet, os_network, os_ports)}
def _add_dhcp_opts_to_port(context, dhcp_options, network_interface, os_port, neutron=None): dhcp_opts = [{'opt_name': 'mtu', 'opt_value': str(CONF.network_device_mtu)}] if dhcp_options is not None: for key, values in dhcp_options['dhcp_configuration'].items(): strvalues = [str(v) for v in values] dhcp_opts.append({'opt_name': DHCP_OPTIONS_MAP[key], 'opt_value': ','.join(strvalues)}) if not neutron: neutron = clients.neutron(context) neutron.update_port(os_port['id'], {'port': {'extra_dhcp_opts': dhcp_opts}})
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 _format_security_groups_ids_names(context): neutron = clients.neutron(context) os_security_groups = neutron.list_security_groups( tenant_id=context.project_id)['security_groups'] security_groups = db_api.get_items(context, 'sg') ec2_security_groups = {} for os_security_group in os_security_groups: security_group = next((g for g in security_groups if g['os_id'] == os_security_group['id']), None) if security_group is None: continue ec2_security_groups[os_security_group['id']] = ( {'groupId': security_group['id'], 'groupName': _translate_group_name(context, os_security_group, security_groups)}) return ec2_security_groups
def detach_internet_gateway(context, internet_gateway_id, vpc_id): igw = ec2utils.get_db_item(context, internet_gateway_id) vpc = ec2utils.get_db_item(context, vpc_id) if igw.get('vpc_id') != vpc['id']: raise exception.GatewayNotAttached(igw_id=igw['id'], vpc_id=vpc['id']) neutron = clients.neutron(context) # TODO(ft): set detaching state into db with common.OnCrashCleaner() as cleaner: _detach_internet_gateway_item(context, igw) cleaner.addCleanup(_attach_internet_gateway_item, context, igw, vpc['id']) try: neutron.remove_gateway_router(vpc["os_id"]) except neutron_exception.NotFound: pass return 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 _format_security_groups_ids_names(context): neutron = clients.neutron(context) os_security_groups = neutron.list_security_groups( tenant_id=context.project_id)['security_groups'] security_groups = db_api.get_items(context, 'sg') ec2_security_groups = {} for os_security_group in os_security_groups: security_group = next((g for g in security_groups if g['os_id'] == os_security_group['id']), None) if security_group is None: continue ec2_security_groups[os_security_group['id']] = ({ 'groupId': security_group['id'], 'groupName': _translate_group_name(context, os_security_group, security_groups) }) return ec2_security_groups
def detach_internet_gateway(context, internet_gateway_id, vpc_id): igw = ec2utils.get_db_item(context, internet_gateway_id) vpc = ec2utils.get_db_item(context, vpc_id) if igw.get("vpc_id") != vpc["id"]: raise exception.GatewayNotAttached(gw_id=igw["id"], vpc_id=vpc["id"]) remove_os_gateway_router = ec2utils.get_attached_gateway(context, vpc_id, "vgw") is None neutron = clients.neutron(context) # TODO(ft): set detaching state into db with common.OnCrashCleaner() as cleaner: _detach_internet_gateway_item(context, igw) cleaner.addCleanup(_attach_internet_gateway_item, context, igw, vpc["id"]) if remove_os_gateway_router: try: neutron.remove_gateway_router(vpc["os_id"]) except neutron_exception.NotFound: pass return True
def create_vpn_connection_route(context, vpn_connection_id, destination_cidr_block): vpn_connection = ec2utils.get_db_item(context, vpn_connection_id) if destination_cidr_block in vpn_connection['cidrs']: return True neutron = clients.neutron(context) vpn_gateway = db_api.get_item_by_id(context, vpn_connection['vpn_gateway_id']) with common.OnCrashCleaner() as cleaner: _add_cidr_to_vpn_connection_item(context, vpn_connection, destination_cidr_block) cleaner.addCleanup(_remove_cidr_from_vpn_connection_item, context, vpn_connection, destination_cidr_block) _reset_vpn_connections(context, neutron, cleaner, vpn_gateway, vpn_connections=[vpn_connection]) return True
def get_os_instance_and_project_id_by_provider_id(context, provider_id, fixed_ip): neutron = clients.neutron(context) os_subnets = neutron.list_subnets(advanced_service_providers=[provider_id], fields=['network_id']) if not os_subnets: raise exception.EC2MetadataNotFound() os_networks = [subnet['network_id'] for subnet in os_subnets['subnets']] try: os_port = neutron.list_ports(fixed_ips='ip_address=' + fixed_ip, network_id=os_networks, fields=['device_id', 'tenant_id'])['ports'][0] except IndexError: raise exception.EC2MetadataNotFound() os_instance_id = os_port['device_id'] project_id = os_port['tenant_id'] return os_instance_id, project_id
def get_os_instance_and_project_id_by_provider_id(context, provider_id, fixed_ip): neutron = clients.neutron(context) os_subnets = neutron.list_subnets(advanced_service_providers=[provider_id], fields=['network_id']) if not os_subnets: raise exception.EC2MetadataNotFound() os_networks = [subnet['network_id'] for subnet in os_subnets['subnets']] try: os_port = neutron.list_ports( fixed_ips='ip_address=' + fixed_ip, network_id=os_networks, fields=['device_id', 'tenant_id'])['ports'][0] except IndexError: raise exception.EC2MetadataNotFound() os_instance_id = os_port['device_id'] project_id = os_port['tenant_id'] return os_instance_id, project_id
def assign_private_ip_addresses(context, network_interface_id, private_ip_address=None, secondary_private_ip_address_count=None, allow_reassignment=False): # TODO(Alex): allow_reassignment is not supported at the moment network_interface = ec2utils.get_db_item(context, network_interface_id) subnet = db_api.get_item_by_id(context, network_interface['subnet_id']) neutron = clients.neutron(context) os_subnet = neutron.show_subnet(subnet['os_id'])['subnet'] os_port = neutron.show_port(network_interface['os_id'])['port'] subnet_ipnet = netaddr.IPNetwork(os_subnet['cidr']) fixed_ips = os_port['fixed_ips'] or [] if private_ip_address is not None: for ip_address in private_ip_address: if netaddr.IPAddress(ip_address) not in subnet_ipnet: raise exception.InvalidParameterValue( value=str(ip_address), parameter='PrivateIpAddress', reason='IP address is out of the subnet range') fixed_ips.append({'ip_address': str(ip_address)}) elif secondary_private_ip_address_count > 0: for _i in range(secondary_private_ip_address_count): fixed_ips.append({'subnet_id': os_subnet['id']}) try: neutron.update_port(os_port['id'], {'port': {'fixed_ips': fixed_ips}}) except neutron_exception.IpAddressGenerationFailureClient: raise exception.InsufficientFreeAddressesInSubnet() except neutron_exception.IpAddressInUseClient: msg = _('Some of %(addresses)s is assigned, but move is not ' 'allowed.') % { 'addresses': private_ip_address } raise exception.InvalidParameterValue(msg) except neutron_exception.BadRequest as ex: # NOTE(ft):AWS returns PrivateIpAddressLimitExceeded, but Neutron does # general InvalidInput (converted to BadRequest) in the same case. msg = _('Specified network interface parameters are invalid. ' 'Reason: %(reason)s') % { 'reason': ex.message } raise exception.InvalidParameterValue(msg) return True
def delete_subnet(context, subnet_id): subnet = ec2utils.get_db_item(context, subnet_id) vpc = db_api.get_item_by_id(context, subnet['vpc_id']) network_interfaces = network_interface_api.describe_network_interfaces( context, filter=[{ 'name': 'subnet-id', 'value': [subnet_id] }])['networkInterfaceSet'] if network_interfaces: msg = _("The subnet '%(subnet_id)s' has dependencies and " "cannot be deleted.") % { 'subnet_id': subnet_id } raise exception.DependencyViolation(msg) neutron = clients.neutron(context) with common.OnCrashCleaner() as cleaner: db_api.delete_item(context, subnet['id']) cleaner.addCleanup(db_api.restore_item, context, 'subnet', subnet) vpn_gateway_api._stop_vpn_in_subnet(context, neutron, cleaner, subnet) try: neutron.remove_interface_router(vpc['os_id'], {'subnet_id': subnet['os_id']}) except neutron_exception.NotFound: pass cleaner.addCleanup(neutron.add_interface_router, vpc['os_id'], {'subnet_id': subnet['os_id']}) try: os_subnet = neutron.show_subnet(subnet['os_id'])['subnet'] except neutron_exception.NotFound: pass else: try: neutron.delete_network(os_subnet['network_id']) except neutron_exception.NetworkInUseClient as ex: LOG.warning( _('Failed to delete network %(os_id)s during ' 'deleting Subnet %(id)s. Reason: %(reason)s'), { 'id': subnet['id'], 'os_id': os_subnet['network_id'], 'reason': ex.message }) return True
def get_os_public_network(context): neutron = clients.neutron(context) search_opts = {'router:external': True, 'name': CONF.external_network} os_networks = neutron.list_networks(**search_opts)['networks'] if len(os_networks) != 1: if CONF.external_network: if len(os_networks) == 0: msg = _LE("No external network with name '%s' is found") else: msg = _LE("More than one external network with name '%s' " "is found") LOG.error(msg, CONF.external_network) else: if len(os_networks) == 0: msg = _LE('No external network is found') else: msg = _LE('More than one external network is found') LOG.error(msg) raise exception.Unsupported(_('Feature is restricted by OS admin')) return os_networks[0]
def allocate_address(self, context, domain=None): if not domain or domain == 'standard': return AddressEngineNova().allocate_address(context) os_public_network = ec2utils.get_os_public_network(context) neutron = clients.neutron(context) with common.OnCrashCleaner() as cleaner: os_floating_ip = {'floating_network_id': os_public_network['id']} try: os_floating_ip = neutron.create_floatingip( {'floatingip': os_floating_ip}) except neutron_exception.OverQuotaClient: raise exception.AddressLimitExceeded() os_floating_ip = os_floating_ip['floatingip'] cleaner.addCleanup(neutron.delete_floatingip, os_floating_ip['id']) address = {'os_id': os_floating_ip['id'], 'public_ip': os_floating_ip['floating_ip_address']} address = db_api.add_item(context, 'eipalloc', address) return address, os_floating_ip
def _update_subnet_host_routes(context, subnet, route_table, cleaner=None, rollback_route_table_object=None, router_objects=None, neutron=None): neutron = neutron or clients.neutron(context) os_subnet = neutron.show_subnet(subnet['os_id'])['subnet'] gateway_ip = str( netaddr.IPAddress(netaddr.IPNetwork(os_subnet['cidr']).first + 1)) host_routes = _get_subnet_host_routes(context, route_table, gateway_ip, router_objects) neutron.update_subnet(subnet['os_id'], {'subnet': { 'host_routes': host_routes }}) if cleaner and rollback_route_table_object: cleaner.addCleanup(_update_subnet_host_routes, context, subnet, rollback_route_table_object)
def get_db_items(self): self.customer_gateways = { cgw['id']: cgw for cgw in db_api.get_items(self.context, 'cgw')} neutron = clients.neutron(self.context) self.os_ikepolicies = { ike['id']: ike for ike in neutron.list_ikepolicies( tenant_id=self.context.project_id)['ikepolicies']} self.os_ipsecpolicies = { ipsec['id']: ipsec for ipsec in neutron.list_ipsecpolicies( tenant_id=self.context.project_id)['ipsecpolicies']} self.os_ipsec_site_connections = { conn['id']: conn for conn in neutron.list_ipsec_site_connections( tenant_id=self.context.project_id)['ipsec_site_connections']} self.external_ips = _get_vpn_gateways_external_ips( self.context, neutron) return super(VpnConnectionDescriber, self).get_db_items()
def delete_vpn_connection_route(context, vpn_connection_id, destination_cidr_block): vpn_connection = ec2utils.get_db_item(context, vpn_connection_id) if destination_cidr_block not in vpn_connection['cidrs']: raise exception.InvalidRouteNotFound( _('The specified route %(destination_cidr_block)s does not exist') % {'destination_cidr_block': destination_cidr_block}) neutron = clients.neutron(context) vpn_gateway = db_api.get_item_by_id(context, vpn_connection['vpn_gateway_id']) with common.OnCrashCleaner() as cleaner: _remove_cidr_from_vpn_connection_item(context, vpn_connection, destination_cidr_block) cleaner.addCleanup(_add_cidr_to_vpn_connection_item, context, vpn_connection, destination_cidr_block) _reset_vpn_connections(context, neutron, cleaner, vpn_gateway, vpn_connections=[vpn_connection]) return True
def unassign_private_ip_addresses(context, network_interface_id, private_ip_address): network_interface = ec2utils.get_db_item(context, network_interface_id) if network_interface['private_ip_address'] in private_ip_address: raise exception.InvalidParameterValue( value=str(network_interface['private_ip_address']), parameter='PrivateIpAddresses', reason='Primary IP address cannot be unassigned') neutron = clients.neutron(context) os_port = neutron.show_port(network_interface['os_id'])['port'] fixed_ips = os_port['fixed_ips'] or [] new_fixed_ips = [ip for ip in fixed_ips if ip['ip_address'] not in private_ip_address] if len(new_fixed_ips) + len(private_ip_address) != len(fixed_ips): msg = _('Some of the specified addresses are not assigned to ' 'interface %(id)s') % {'id': network_interface_id} raise exception.InvalidParameterValue(msg) os_port = neutron.update_port(os_port['id'], {'port': {'fixed_ips': new_fixed_ips}}) return True
def _update_routes_in_associated_subnets(context, cleaner, route_table, default_associations_only=None, update_target=None): if default_associations_only: appropriate_rtb_ids = (None,) else: vpc = db_api.get_item_by_id(context, route_table['vpc_id']) if vpc['route_table_id'] == route_table['id']: appropriate_rtb_ids = (route_table['id'], None) else: appropriate_rtb_ids = (route_table['id'],) neutron = clients.neutron(context) subnets = [subnet for subnet in db_api.get_items(context, 'subnet') if (subnet['vpc_id'] == route_table['vpc_id'] and subnet.get('route_table_id') in appropriate_rtb_ids)] # NOTE(ft): we need to update host routes for both host and vpn target # because vpn-related routes are present in host routes as well _update_host_routes(context, neutron, cleaner, route_table, subnets) if not update_target or update_target == VPN_TARGET: vpn_connection_api._update_vpn_routes(context, neutron, cleaner, route_table, subnets)
def create_vpc(context, cidr_block, instance_tenancy='default'): neutron = clients.neutron(context) with common.OnCrashCleaner() as cleaner: os_router_body = {'router': {}} try: os_router = neutron.create_router(os_router_body)['router'] except neutron_exception.OverQuotaClient: raise exception.VpcLimitExceeded() cleaner.addCleanup(neutron.delete_router, os_router['id']) vpc = db_api.add_item(context, 'vpc', {'os_id': os_router['id'], 'cidr_block': cidr_block}) cleaner.addCleanup(db_api.delete_item, context, vpc['id']) route_table = route_table_api._create_route_table(context, vpc) cleaner.addCleanup(route_table_api._delete_route_table, context, route_table['id']) vpc['route_table_id'] = route_table['id'] db_api.update_item(context, vpc) neutron.update_router(os_router['id'], {'router': {'name': vpc['id']}}) security_group_api._create_default_security_group(context, vpc) return {'vpc': _format_vpc(vpc)}
def delete_network_interface(context, network_interface_id): network_interface = ec2utils.get_db_item(context, network_interface_id) if 'instance_id' in network_interface: msg = _("Network interface '%(eni_id)s' is currently in use.") msg = msg % {'eni_id': network_interface_id} raise exception.InvalidParameterValue(msg) for address in db_api.get_items(context, 'eipalloc'): if address.get('network_interface_id') == network_interface['id']: address_api._disassociate_address_item(context, address) neutron = clients.neutron(context) with common.OnCrashCleaner() as cleaner: db_api.delete_item(context, network_interface['id']) cleaner.addCleanup(db_api.restore_item, context, 'eni', network_interface) try: neutron.delete_port(network_interface['os_id']) except neutron_exception.PortNotFoundClient: pass return True
def assign_private_ip_addresses(context, network_interface_id, private_ip_address=None, secondary_private_ip_address_count=None, allow_reassignment=False): # TODO(Alex): allow_reassignment is not supported at the moment network_interface = ec2utils.get_db_item(context, network_interface_id) subnet = db_api.get_item_by_id(context, network_interface['subnet_id']) neutron = clients.neutron(context) os_subnet = neutron.show_subnet(subnet['os_id'])['subnet'] os_port = neutron.show_port(network_interface['os_id'])['port'] subnet_ipnet = netaddr.IPNetwork(os_subnet['cidr']) fixed_ips = os_port['fixed_ips'] or [] if private_ip_address is not None: for ip_address in private_ip_address: if netaddr.IPAddress(ip_address) not in subnet_ipnet: raise exception.InvalidParameterValue( value=str(ip_address), parameter='PrivateIpAddress', reason='IP address is out of the subnet range') fixed_ips.append({'ip_address': str(ip_address)}) elif secondary_private_ip_address_count > 0: for _i in range(secondary_private_ip_address_count): fixed_ips.append({'subnet_id': os_subnet['id']}) try: neutron.update_port(os_port['id'], {'port': {'fixed_ips': fixed_ips}}) except neutron_exception.IpAddressGenerationFailureClient: raise exception.NetworkInterfaceLimitExceeded( subnet_id=subnet['id']) except neutron_exception.IpAddressInUseClient: msg = _('Some of %(addresses)s is assigned, but move is not ' 'allowed.') % {'addresses': private_ip_address} raise exception.InvalidParameterValue(msg) except neutron_exception.BadRequest as ex: # NOTE(ft):AWS returns PrivateIpAddressLimitExceeded, but Neutron does # general InvalidInput (converted to BadRequest) in the same case. msg = _('Specified network interface parameters are invalid. ' 'Reason: %(reason)s') % {'reason': ex.message} raise exception.InvalidParameterValue(msg) return True
def delete_subnet(context, subnet_id): subnet = ec2utils.get_db_item(context, subnet_id) vpc = db_api.get_item_by_id(context, subnet['vpc_id']) network_interfaces = network_interface_api.describe_network_interfaces( context, filter=[{'name': 'subnet-id', 'value': [subnet_id]}])['networkInterfaceSet'] if network_interfaces: msg = _("The subnet '%(subnet_id)s' has dependencies and " "cannot be deleted.") % {'subnet_id': subnet_id} raise exception.DependencyViolation(msg) neutron = clients.neutron(context) with common.OnCrashCleaner() as cleaner: db_api.delete_item(context, subnet['id']) cleaner.addCleanup(db_api.restore_item, context, 'subnet', subnet) vpn_gateway_api._stop_vpn_in_subnet(context, neutron, cleaner, subnet) try: neutron.remove_interface_router(vpc['os_id'], {'subnet_id': subnet['os_id']}) except neutron_exception.NotFound: pass cleaner.addCleanup(neutron.add_interface_router, vpc['os_id'], {'subnet_id': subnet['os_id']}) try: os_subnet = neutron.show_subnet(subnet['os_id'])['subnet'] except neutron_exception.NotFound: pass else: try: neutron.delete_network(os_subnet['network_id']) except neutron_exception.NetworkInUseClient as ex: LOG.warning(_('Failed to delete network %(os_id)s during ' 'deleting Subnet %(id)s. Reason: %(reason)s'), {'id': subnet['id'], 'os_id': os_subnet['network_id'], 'reason': ex.message}) return True
def attach_internet_gateway(context, internet_gateway_id, vpc_id): igw = ec2utils.get_db_item(context, internet_gateway_id) if igw.get("vpc_id"): msg_params = {"igw_id": igw["id"], "vpc_id": igw["vpc_id"]} msg = _("resource %(igw_id)s is already attached to " "network %(vpc_id)s") % msg_params raise exception.ResourceAlreadyAssociated(msg) vpc = ec2utils.get_db_item(context, vpc_id) if ec2utils.get_attached_gateway(context, vpc["id"], "igw"): msg = _("Network %(vpc_id)s already has an internet gateway " "attached") % {"vpc_id": vpc["id"]} raise exception.InvalidParameterValue(msg) external_network_id = None if not ec2utils.get_attached_gateway(context, vpc["id"], "vgw"): external_network_id = ec2utils.get_os_public_network(context)["id"] neutron = clients.neutron(context) # TODO(ft): set attaching state into db with common.OnCrashCleaner() as cleaner: _attach_internet_gateway_item(context, igw, vpc["id"]) cleaner.addCleanup(_detach_internet_gateway_item, context, igw) if external_network_id: neutron.add_gateway_router(vpc["os_id"], {"network_id": external_network_id}) return True
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