Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Errors and inconsistent data when deleting cables terminated to circuits #1694

Closed
glennmatthews opened this issue Apr 25, 2022 · 8 comments · Fixed by #2050
Closed

Errors and inconsistent data when deleting cables terminated to circuits #1694

glennmatthews opened this issue Apr 25, 2022 · 8 comments · Fixed by #2050
Assignees
Labels
type: bug Something isn't working as expected

Comments

@glennmatthews
Copy link
Contributor

Environment

  • Python version:
  • Nautobot version: 1.3.2

Steps to Reproduce

  1. Create a device and add interfaces to it
  2. Create a circuit and add A and Z terminations to it
  3. Connect the A termination to an interface of the device
  4. Connect the Z termination to an interface of the device
  5. Attempt to disconnect either termination

Expected Behavior

Cable to be deleted

Observed Behavior

Cable is reported as deleted, but still exists in the UI, even after a cacheops.invalidate_all() is run. On attempting to disconnect the cable a second time, the following traceback is seen:

14:56:07.429 ERROR   django.request :
  Internal Server Error: /dcim/cables/7f3a3352-0fb7-43f9-9e85-971037f553f3/delete/
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/django/db/models/fields/related_descriptors.py", line 173, in __get__
    rel_obj = self.field.get_cached_value(instance)
  File "/usr/local/lib/python3.7/site-packages/django/db/models/fields/mixins.py", line 15, in get_cached_value
    return instance._state.fields_cache[cache_name]
KeyError: '_path'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.7/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.7/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/source/nautobot/utilities/views.py", line 94, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/source/nautobot/core/views/generic.py", line 456, in post
    obj.delete()
  File "/usr/local/lib/python3.7/site-packages/django/db/models/base.py", line 967, in delete
    return collector.delete()
  File "/usr/local/lib/python3.7/site-packages/django/db/models/deletion.py", line 436, in delete
    sender=model, instance=obj, using=self.using
  File "/usr/local/lib/python3.7/site-packages/django/dispatch/dispatcher.py", line 182, in send
    for receiver in self._live_receivers(sender)
  File "/usr/local/lib/python3.7/site-packages/django/dispatch/dispatcher.py", line 182, in <listcomp>
    for receiver in self._live_receivers(sender)
  File "/source/nautobot/dcim/signals.py", line 177, in nullify_connected_endpoints
    instance.termination_b.save()
  File "/source/nautobot/dcim/models/device_components.py", line 512, in save
    return super().save(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/django/db/models/base.py", line 740, in save
    force_update=force_update, update_fields=update_fields)
  File "/usr/local/lib/python3.7/site-packages/django/db/models/base.py", line 789, in save_base
    update_fields=update_fields, raw=raw, using=using,
  File "/usr/local/lib/python3.7/site-packages/django/dispatch/dispatcher.py", line 182, in send
    for receiver in self._live_receivers(sender)
  File "/usr/local/lib/python3.7/site-packages/django/dispatch/dispatcher.py", line 182, in <listcomp>
    for receiver in self._live_receivers(sender)
  File "/source/nautobot/utilities/utils.py", line 354, in _curried
    return _curried_func(*args, *moreargs, **{**kwargs, **morekwargs})
  File "/source/nautobot/extras/signals.py", line 72, in _handle_changed_object
    objectchange = instance.to_objectchange(action)
  File "/source/nautobot/dcim/models/device_components.py", line 93, in to_objectchange
    object_data_v2=serialize_object_v2(self),
  File "/source/nautobot/utilities/utils.py", line 181, in serialize_object_v2
    data = serializer_class(obj, context={"request": None}).data
  File "/usr/local/lib/python3.7/site-packages/rest_framework/serializers.py", line 555, in data
    ret = super().data
  File "/usr/local/lib/python3.7/site-packages/rest_framework/serializers.py", line 253, in data
    self._data = self.to_representation(self.instance)
  File "/usr/local/lib/python3.7/site-packages/rest_framework/serializers.py", line 522, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "/usr/local/lib/python3.7/site-packages/rest_framework/fields.py", line 1886, in to_representation
    return method(value)
  File "/source/nautobot/dcim/api/serializers.py", line 163, in get_connected_endpoint
    if obj._path is not None and obj._path.destination is not None:
  File "/usr/local/lib/python3.7/site-packages/django/db/models/fields/related_descriptors.py", line 187, in __get__
    rel_obj = self.get_object(instance)
  File "/usr/local/lib/python3.7/site-packages/django/db/models/fields/related_descriptors.py", line 154, in get_object
    return qs.get(self.field.get_reverse_related_filter(instance))
  File "/usr/local/lib/python3.7/site-packages/cacheops/query.py", line 351, in get
    return qs._no_monkey.get(qs, *args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/django/db/models/query.py", line 437, in get
    self.model._meta.object_name
nautobot.dcim.models.cables.CablePath.DoesNotExist: CablePath matching query does not exist.
@glennmatthews glennmatthews added type: bug Something isn't working as expected group: dcim labels Apr 25, 2022
@glennmatthews glennmatthews moved this to To Groom in Nautobot Core ⚙️ Apr 25, 2022
@jathanism
Copy link
Contributor

I confirmed that this behavior occurs both with or without caching enabled, so it's absolutely a bug in the business logic.

@jathanism
Copy link
Contributor

jathanism commented Apr 26, 2022

Possibly related: Suor/django-cacheops#348 (comment)

@jathanism
Copy link
Contributor

Under normal circumstances Interface._path should return None when unassigned. There's some state inconsistency that is being introduced here where the queryset is attempting to retrieve the value of _path from the internal field cache on the instance and it's failing. The pattern for deletion of the CablePath object is to be at play here and needs to be reviewed.

@jathanism
Copy link
Contributor

jathanism commented May 3, 2022

Let's try to remove cacheops from the equation entirely and see if this issue persists, just to rule it out.

@jathanism
Copy link
Contributor

Let's try to remove cacheops from the equation entirely and see if this issue persists, just to rule it out.

Still crashed. Here is a Sentry report for it: https://sentry.io/share/issue/59b831e46b4f4cc69485c49f97302654/

@glennmatthews
Copy link
Contributor Author

Appears to be a pretty tangled chain of function calls what with a delete() call triggering a post_delete signal triggering a post_save signal...

@timber-schroeder
Copy link

👍 just ran into this one also on 1.3.2, with identical replication steps.

I have had CACHEOPS_ENABLED = False set since a long time before the circuit+termination in question existed so yeah its definitely not caching related.

Worked around for now in the few instances I had by just manually deleting all the relevant references and rows in the db.

@dd1245
Copy link

dd1245 commented Jun 24, 2022

👍 just ran into this one also on 1.3.2, with identical replication steps.

I have had CACHEOPS_ENABLED = False set since a long time before the circuit+termination in question existed so yeah its definitely not caching related.

Worked around for now in the few instances I had by just manually deleting all the relevant references and rows in the db.

I think I'll have to do something manual as well, I can't really keep waiting for a fix. Which tables did you have to make manual delete operations on?

@glennmatthews glennmatthews changed the title Issues when deleting cables terminated to circuits Errors and inconsistent data when deleting cables terminated to circuits Jul 5, 2022
@timizuoebideri1 timizuoebideri1 self-assigned this Jul 7, 2022
@timizuoebideri1 timizuoebideri1 moved this from To Groom to In Progress in Nautobot Core ⚙️ Jul 8, 2022
@timizuoebideri1 timizuoebideri1 moved this from In Progress to In Review in Nautobot Core ⚙️ Jul 13, 2022
@jathanism jathanism moved this from In Review to Reviewer Approved in Nautobot Core ⚙️ Jul 21, 2022
Repository owner moved this from Reviewer Approved to Done in Nautobot Core ⚙️ Jul 25, 2022
smk4664 added a commit to smk4664/nautobot that referenced this issue Jul 29, 2022
* next: (26 commits)
  Include relationships and associations on object REST APIs (nautobot#2092)
  Add release-note for nautobot#2116
  Update Releases Batched for Next (next) (nautobot#2116)
  Re-ordered migrations
  Add release-note for nautobot#1226, nautobot#1739, nautobot#2115
  Add custom job intervals (nautobot#2084)
  Implement Notes Model (nautobot#1984)
  Update Lock-file Patch Releases for Develop (nautobot#2115)
  update paginator to enforce max_page_size setting in web ui views (nautobot#2112)
  Add missing location status migration (nautobot#2100)
  update release-notes for issue nautobot#2060
  added peer_id filter for relationship associations (nautobot#2113)
  Add release-note for nautobot#2025
  Cleanup group names, manual approval for flake8 (nautobot#2025)
  updated documentations for nautobot#2109 and nautobot#2111
  fixed one to many relationship source filter and apply AND operator between filters (nautobot#2111)
  Version bump to v1.3.10-beta.1, seeded next version in docs.
  Add release-note for nautobot#860, nautobot#1694, nautobot#2081. Update release date, version.
  Fix nautobot#2077 - handle case on object detail views where a relationship involves a non-installed model (nautobot#2078)
  Fix error raised if status connected not found when creating a cable (nautobot#2089)
  ...

# Conflicts:
#	nautobot/circuits/api/serializers.py
#	nautobot/core/api/serializers.py
#	nautobot/dcim/api/serializers.py
#	nautobot/docs/development/best-practices.md
#	nautobot/docs/development/style-guide.md
#	nautobot/docs/release-notes/version-1.4.md
#	nautobot/extras/api/nested_serializers.py
#	nautobot/extras/api/relationships.py
#	nautobot/extras/api/serializers.py
#	nautobot/extras/tests/integration/test_notes.py
#	nautobot/extras/tests/test_api.py
#	nautobot/utilities/testing/api.py
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 24, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
type: bug Something isn't working as expected
Projects
No open projects
Archived in project
5 participants