def get_ptr_from_ip(ip, region_name, request_session=None) -> dict: params = {'ip': ip, 'region_name': region_name} serializer = GetPtrFromIpSerializer(data=params) serializer.is_valid(raise_exception=True) if request_session: designate = designate_client(api_session=IdentityAdminApi( request_session=request_session).session, region_name=serializer.validated_data.pop( 'region_name', None)) else: designate = designate_client(api_session=IdentityAdminApi().session, region_name=serializer.validated_data.pop( 'region_name', None)) related_ip = ip_address(serializer.validated_data['ip']) ptr_record = related_ip.reverse_pointer + '.' if isinstance(related_ip, IPv6Address): zone_name = ptr_record else: # cut the first segment (last segment from the ip) zone_name = ptr_record[ptr_record.index('.') + 1:] try: zones = designate.zones.list(criterion={'name': zone_name}) except (designate_exceptions.Base, ClientException) as e: raise e if zones: zone_id = zones[0]['id'] try: recordsets = designate.recordsets.list(zone=zone_id, criterion={ 'type': 'PTR', 'name': ptr_record }) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to list record sets, reason {0}'.format(e)) raise e if recordsets: # TODO(erno): returns only the first PTR entry, and the first record record = recordsets[0]['records'][0] if record.endswith('.'): record = record[:-1] return dict( record=record, zone_id=zone_id, ) else: dict( record='', zone_id=zone_id, ) return dict( record='', zone_id='', )
def create(self, request): """Create a dns zone""" if not validate_cloud_objects_limit(): raise APIBadRequest(_('Licence cloud objects limit reached. Please check your license.')) serializer = DnsCreateSerializer(data=request.data) serializer.is_valid(raise_exception=True) designate = designate_client(self.identity_admin_api.session, region_name=serializer.validated_data.pop('region_name', None), sudo_project_id=serializer.validated_data.pop('sudo_project_id', None), all_projects=serializer.validated_data.pop('all_projects', None)) serializer.validated_data.pop('client', None) try: zone = designate.zones.create(**serializer.validated_data) except designate_exceptions.Conflict as e: LOG.error('Unable to create zone, reason {0}'.format(e)) raise ValidationError( {'detail': _('Unable to create zone. A zone with the same domain name already exists')} ) except designate_exceptions.Base as e: LOG.error('Unable to create zone, reason {0}'.format(e)) raise ValidationError({'detail': _('Unable to create zone. Please see logs for more info')}) else: return Response(zone, status=HTTP_201_CREATED)
def update_record(self, request, pk=None): serializer = RecordSetAlterSerializer(data=request.data) serializer.is_valid(raise_exception=True) api_session = get_api_session(request) designate = designate_client(api_session, region_name=serializer.validated_data.pop( 'region_name', None)) try: recordsets = designate.recordsets.update( zone=pk, recordset=request.data.get('pk'), values=serializer.validated_data) except (designate_exceptions.NotFound, designate_exceptions.ResourceNotFound) as e: LOG.error(e) raise NotFound(detail=_('Zone or record not found')) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to update record, reason {0}'.format(e)) raise ValidationError({ 'detail': _('Unable to update record. Please contact support for more info' ) }) else: return Response(recordsets, status=HTTP_200_OK)
def list_records(self, request, pk=None): serializer = RecordSetListSerializer(data=request.query_params) serializer.is_valid(raise_exception=True) api_session = get_api_session(request) designate = designate_client(api_session, region_name=serializer.validated_data.pop( 'region_name', None)) try: serializer.validated_data['sort_key'] = 'type' recordsets = designate.recordsets.list( zone=pk, criterion=serializer.validated_data) except (designate_exceptions.NotFound, designate_exceptions.ResourceNotFound) as e: LOG.error(e) raise NotFound(detail=_('Zone not found')) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to list records, reason {0}'.format(e)) raise ValidationError({ 'detail': _('Unable to list records. Please contact support for more info' ) }) else: response = ListRecordsSerializer(instance=recordsets).data response['record_types'] = [ x[0] for x in RECORD_TYPES if x[0] != 'SOA' ] return Response(response)
def list(self, request): """List all dns zones belonging to a region""" serializer = DnsFilterSerializer(data=request.query_params) serializer.is_valid(raise_exception=True) api_session = get_api_session(request) designate = designate_client(api_session, region_name=serializer.validated_data.pop( 'region_name', None)) search_params, page_limit, custom_filtering_params = get_filter_params( request) criterion = {**search_params, **serializer.validated_data} try: zones = designate.zones.list(criterion=criterion, limit=page_limit) except (designate_exceptions.NotFound, designate_exceptions.ResourceNotFound) as e: LOG.error(e) raise NotFound(detail=_('No zones found')) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to list zones, reason {0}'.format(e)) raise ValidationError(detail=_( 'Unable to list zones. Please contact support for more info')) else: rsp = { 'objects': DnsSerializer(instance=zones, many=True).data, 'permissions': permissions_cache.get_view_permissions(request.user, self.basename), 'hasMore': zones.next_page } return Response(rsp)
def delete_record(self, request, pk=None): designate = designate_client(self.identity_admin_api.session, region_name=request.query_params.get('region_name'), all_projects=request.query_params.get('all_projects')) try: recordsets = designate.recordsets.delete(zone=pk, recordset=request.query_params.get('pk')) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to delete record, reason {0}'.format(e)) raise ValidationError({'detail': _('Unable to delete record. Please see logs for more info')}) else: return Response(recordsets, status=HTTP_204_NO_CONTENT)
def destroy(self, request, pk=None): """Delete a dns zone""" designate = designate_client(self.identity_admin_api.session, region_name=request.query_params.get('region_name', None), all_projects=True) try: designate.zones.delete(zone=pk) except designate_exceptions.Base as e: LOG.error('Unable to delete zone, reason {0}'.format(e)) raise ValidationError({'detail': _('Unable to delete zone. Please see logs for more info')}) else: return Response({'detail': _('Zone deleted')}, status=HTTP_204_NO_CONTENT)
def retrieve(self, request, pk=None): """Fetches a dns zone""" designate = designate_client(self.identity_admin_api.session, region_name=request.query_params.get('region_name', None), sudo_project_id=request.query_params.get('sudo_project_id', None), all_projects=request.query_params.get('all_projects', True)) try: zone = designate.zones.get(zone=pk) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to fetch zone, reason {0}'.format(e)) raise ValidationError({'detail': _('Unable to fetch zone. Please see logs for more info')}) return Response(DnsSerializer(instance=zone).data)
def create_records(self, request, pk=None): serializer = RecordSetCreateSerializer(data=request.data) serializer.is_valid(raise_exception=True) designate = designate_client(self.identity_admin_api.session, region_name=serializer.validated_data.pop('region_name', None,), sudo_project_id=serializer.validated_data.pop('sudo_project_id', None)) try: records = designate.recordsets.create(zone=pk, **serializer.validated_data) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to create record in zone {0}, reason {1}'.format(pk, e)) raise ValidationError({'detail': _('Unable to create record. Please see logs for more info')}) else: return Response(records, status=HTTP_201_CREATED)
def update(self, request, pk=None): """Updates a dns zone""" serializer = DnsUpdateSerializer(data=request.data) serializer.is_valid(raise_exception=True) designate = designate_client(self.identity_admin_api.session, region_name=serializer.validated_data.pop('region_name', None), sudo_project_id=serializer.validated_data.pop('sudo_project_id', None), all_projects=serializer.validated_data.pop('all_projects', None)) try: zone = designate.zones.update(zone=pk, values=serializer.validated_data) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to update zone, reason {0}'.format(e)) raise ValidationError({'detail': e}) else: return Response(zone, status=HTTP_200_OK)
def update_record(self, request, pk=None): serializer = RecordSetUpdateSerializer(data=request.data) serializer.is_valid(raise_exception=True) designate = designate_client(self.identity_admin_api.session, region_name=serializer.validated_data.pop('region_name', None), all_projects=serializer.validated_data.pop('all_projects', None)) try: recordsets = designate.recordsets.update(zone=pk, recordset=request.data.get('pk'), values=serializer.validated_data) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to update record, reason {0}'.format(e)) raise ValidationError({'detail': _('Unable to update record. Please see longs for more info')}) else: return Response(recordsets, status=HTTP_200_OK)
def list(self, request): """List all dns zones belonging to a region""" serializer = DnsFilterSerializer(data=request.query_params) serializer.is_valid(raise_exception=True) search_params, page_limit, custom_filtering_params = get_filter_params(request) all_projects = serializer.validated_data.pop('all_projects', None) # custom filtering by client custom_api_session = None client_id = custom_filtering_params.get('client', None) if custom_filtering_params else None if client_id: client = Client.objects.get(id=client_id) project = client.first_project if not project: raise APIBadRequest(_('Client you want zones for does not have an openstack project.')) custom_api_session = IdentityUserApi( project.project_id, project.project_domain_id, cache=request.session ).session all_projects = None designate = designate_client(self.identity_admin_api.session if not custom_api_session else custom_api_session, region_name=serializer.validated_data.pop('region_name', None), sudo_project_id=serializer.validated_data.pop('sudo_project_id', None), all_projects=all_projects) criterion = {**search_params, **serializer.validated_data} try: zones = designate.zones.list(criterion=criterion, limit=page_limit) except (designate_exceptions.NotFound, designate_exceptions.ResourceNotFound) as e: LOG.error(e) raise NotFound(detail=_('No zones found')) except designate_exceptions.Base as e: LOG.error('Unable to list zones, reason {0}'.format(e)) raise ValidationError({'detail': _('Unable to list zones. Please see logs for more info')}) except EndpointNotFound as e: LOG.error('Endpoint not found: {}'.format(e)) raise NotFound(detail=_('DSN endpoint not found')) else: rsp = {'objects': DnsSerializer(instance=zones, many=True).data, 'count': len(zones), 'hasMore': zones.next_page} return Response(rsp)
def retrieve(self, request, pk=None): """Fetches a dns zone""" api_session = get_api_session(request) designate = designate_client(api_session, region_name=request.query_params.get( 'region_name', None)) try: zone = designate.zones.get(zone=pk) except (designate_exceptions.NotFound, designate_exceptions.ResourceNotFound) as e: LOG.error(e) raise NotFound(detail=_('Zone not found')) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to fetch zone, reason {0}'.format(e)) raise ValidationError(detail=_( 'Unable to fetch zone. Please contact support for more info')) return Response(DnsSerializer(instance=zone).data)
def create_records(self, request, pk=None): serializer = RecordSetCreateSerializer(data=request.data) serializer.is_valid(raise_exception=True) api_session = get_api_session(request) designate = designate_client(api_session, region_name=serializer.validated_data.pop( 'region_name', None)) try: records = designate.recordsets.create(zone=pk, **serializer.validated_data) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to create record in zone {0}, reason {1}'.format( pk, e)) raise ValidationError(detail=_( 'Unable to create record. Please contact support for more info' )) else: return Response(records, status=HTTP_201_CREATED)
def delete_record(self, request, pk=None): api_session = get_api_session(request) designate = designate_client( api_session, region_name=request.data.get('region_name')) try: recordsets = designate.recordsets.delete( zone=pk, recordset=request.data.get('pk')) except (designate_exceptions.NotFound, designate_exceptions.ResourceNotFound) as e: LOG.error(e) raise NotFound(detail=_('Record not found')) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to delete record, reason {0}'.format(e)) raise ValidationError({ 'detail': _('Unable to delete record. Please contact support for more info' ) }) else: return Response(recordsets, status=HTTP_204_NO_CONTENT)
def create(self, request): """Create a dns zone""" if not validate_cloud_objects_limit(): raise APIBadRequest( _('Failed to create DNS zone. Please contact support.')) serializer = DnsCreateSerializer(data=request.data) serializer.is_valid(raise_exception=True) api_session = get_api_session(request) designate = designate_client(api_session, region_name=serializer.validated_data.pop( 'region_name', None)) try: zone = designate.zones.create(**serializer.validated_data) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to create zone, reason {0}'.format(e)) raise ValidationError({'detail': e}) else: return Response(zone, status=HTTP_201_CREATED)
def list_records(self, request, pk=None): serializer = RecordSetListSerializer(data=request.query_params) serializer.is_valid(raise_exception=True) recordset_default_limit = getattr(settings, 'OPENSTACK_DESIGNATE_RECORDSET_LIMIT', 100000) records_limit = serializer.validated_data.pop('limit', recordset_default_limit) designate = designate_client(self.identity_admin_api.session, region_name=serializer.validated_data.pop('region_name', None), all_projects=serializer.validated_data.pop('all_projects', None)) try: serializer.validated_data['sort_key'] = 'type' recordsets = designate.recordsets.list(zone=pk, criterion=serializer.validated_data, limit=records_limit) except (designate_exceptions.NotFound, designate_exceptions.ResourceNotFound) as e: LOG.error(e) raise NotFound(detail=_('Zone not found')) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to list records, reason {0}'.format(e)) raise ValidationError({'detail': str(e)}) else: response = ListRecordsSerializer(instance=recordsets).data response['record_types'] = [x[0] for x in RECORD_TYPES if x[0] != 'SOA'] return Response(response)
def update(self, request, pk=None): """Updates a dns zone""" serializer = DnsUpdateSerializer(data=request.data) serializer.is_valid(raise_exception=True) api_session = get_api_session(request) designate = designate_client(api_session, region_name=serializer.validated_data.pop( 'region_name', None)) try: zone = designate.zones.update(zone=pk, values=serializer.validated_data) except (designate_exceptions.NotFound, designate_exceptions.ResourceNotFound) as e: LOG.error(e) raise NotFound(detail=_('Zone not found')) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to update zone, reason {0}'.format(e)) raise ValidationError({'detail': e}) else: return Response(zone, status=HTTP_200_OK)
def destroy(self, request, pk=None): """Delete a dns zone""" api_session = get_api_session(request) designate = designate_client(api_session, region_name=request.query_params.get( 'region_name', None)) try: designate.zones.delete(zone=pk) except (designate_exceptions.NotFound, designate_exceptions.ResourceNotFound) as e: LOG.error(e) raise NotFound(detail=_('Zone not found')) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to delete zone, reason {0}'.format(e)) raise ValidationError({ 'detail': _('Unable to delete zone. Please contact support for more info' ) }) else: return Response({'detail': _('Zone deleted')}, status=HTTP_204_NO_CONTENT)
def create_or_update_ptr(ip, record, region_name, zone_id=None, request=None): data = dict( ip=ip, record=record, region_name=region_name, ) if zone_id: data['zone_id'] = zone_id serializer = CreateOrUpdatePtrSerializer(data=data) serializer.is_valid(raise_exception=True) if request: designate = designate_client(api_session=IdentityAdminApi( request_session=request.session).session, region_name=serializer.validated_data.pop( 'region_name', None)) else: designate = designate_client(api_session=IdentityAdminApi().session, region_name=serializer.validated_data.pop( 'region_name', None)) try: zone_id, created = get_or_create_zone(designate=designate, request=request, data=data) except (designate_exceptions.Base, designate_exceptions.RemoteError) as e: raise e record = serializer.validated_data['record'] if not record.endswith('.'): record += '.' # update or create PTR record if created: recordset_name = ip_address( serializer.validated_data['ip']).reverse_pointer + '.' try: record = designate.recordsets.create(zone=zone_id, records=[record], name=recordset_name, type_='PTR') except (designate_exceptions.BadRequest, ClientException) as e: raise e else: try: ptr_record = ip_address( serializer.validated_data['ip']).reverse_pointer + '.' recordsets = designate.recordsets.list(zone=zone_id, criterion={ 'type': 'PTR', 'name': ptr_record }) except designate_exceptions.Base as e: LOG.error('Unable to list record sets, reason {0}'.format(e)) raise e try: if recordsets: record = designate.recordsets.update( zone=zone_id, recordset=recordsets[0]['id'], values={'records': [record]}) else: recordset_name = ip_address( serializer.validated_data['ip']).reverse_pointer + '.' record = designate.recordsets.create(zone=zone_id, records=[record], name=recordset_name, type_='PTR') except (designate_exceptions.BadRequest, ClientException, designate_exceptions.Conflict) as e: raise e return dict(record=record)
def synchronize_records(self, request, pk): serializer = SyncRecordSetsSerializer(data=request.data, many=True) serializer.is_valid(raise_exception=True) current_recordsets = serializer.validated_data for recordset_i in current_recordsets: for recordset_j in current_recordsets: if recordset_i['id'] == recordset_j['id']: continue if recordset_i['name'] == recordset_j['name'] and recordset_i['type'] == recordset_j['type']: raise ValidationError({'detail': _('More than one recordset exists with the same subdomain ' '{subd} and type {type} exist' .format(subd=recordset_i['name'], type=recordset_i['type']))}) designate = designate_client(self.identity_admin_api.session, all_projects=True, edit_managed=True) try: recordset_default_limit = getattr(settings, 'OPENSTACK_DESIGNATE_RECORDSET_LIMIT', 100000) existing_recordsets = designate.recordsets.list(zone=pk, limit=recordset_default_limit) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to list records, reason {0}'.format(e)) raise ValidationError({'detail': _('Unable to list records. Please contact support for more info')}) # create, update and delete recordsets create_recordsets, update_recordsets, delete_recordsets = \ get_recordsets_changes(current_recordsets, existing_recordsets) # TODO(erno): make a celery task for this, refactor frontend too errors = {} create_errors = '' for recordset in create_recordsets: try: designate.recordsets.create(zone=pk, name=recordset['name'], type_=recordset['type'], records=recordset['records'], ttl=recordset['ttl']) except (designate_exceptions.Base, ClientException) as e: create_errors += '{}\n'.format(remove_unicode(str(e))) if create_errors: errors['detail'] = create_errors for recordset in update_recordsets: try: designate.recordsets.update(zone=pk, recordset=recordset['id'], values={'records': recordset['records'], 'ttl': recordset['ttl']}) except (designate_exceptions.Base, ClientException) as e: errors[recordset['id']] = remove_unicode(str(e)) for record_id in delete_recordsets: try: designate.recordsets.delete(zone=pk, recordset=record_id) except (designate_exceptions.Base, ClientException) as e: errors[record_id] = remove_unicode(str(e)) if errors: raise ValidationError(errors) try: recordsets = designate.recordsets.list(zone=pk) except (designate_exceptions.Base, ClientException) as e: LOG.error('Unable to list records, reason {0}'.format(e)) raise ValidationError({'detail': str(e)}) else: response = ListRecordsSerializer(instance=recordsets).data response['record_types'] = [x[0] for x in RECORD_TYPES if x[0] != 'SOA'] response['detail'] = _('Recordsets update scheduled') return Response(response)