Skip to content

Commit

Permalink
[Fix] Consumption were not calculated on resource deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
Sispheor committed Apr 24, 2024
1 parent 2e39487 commit ac397f0
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 11 deletions.
11 changes: 7 additions & 4 deletions resource_tracker_v2/api/serializers/resource_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,9 @@ def create(self, validated_data):
resource_attributes = validated_data.pop('resource_attributes', list())
new_resource = super().create(validated_data)
for attribute in resource_attributes:

attribute_definition = AttributeDefinition.objects.get(name=attribute["attribute_definition"].get('name'))
ResourceAttribute.objects.create(value=attribute.pop('value'),
resource=new_resource,
attribute_definition=attribute_definition)
new_resource.set_attribute(attribute_definition, attribute.pop('value'))
return new_resource

def update(self, instance, validated_data):
Expand All @@ -80,7 +79,11 @@ def update(self, instance, validated_data):
# the resource attribute is not yet created
ResourceAttribute.objects.create(resource=instance, attribute_definition=attribute_def,
value=attribute.get('value', 0))

# notify transformer (we should have only one single transformer)
transformer = Transformer.objects.get(attribute_definition=attribute_def,
resource_group=instance.resource_group)
transformer.calculate_total_produced()
transformer.notify_parent()
except AttributeDefinition.DoesNotExist:
raise serializers.ValidationError({
attribute_item_name: f"'{attribute_item_name}' is not a valid attribute of the resource group {instance.resource_group.name}"
Expand Down
39 changes: 39 additions & 0 deletions resource_tracker_v2/migrations/0006_force_calculate_consumption.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Generated by Django 4.2.5 on 2024-04-24 13:49

from django.db import migrations


def update_all_resource_consumption(apps, schema_editor):
Transformer = apps.get_model('resource_tracker_v2', 'Transformer')
ResourceAttribute = apps.get_model('resource_tracker_v2', 'ResourceAttribute')

for transformer in Transformer.objects.all():
# update total produced
total_produced = 0
all_resource_att = ResourceAttribute.objects.filter(
resource_id__in=transformer.resource_group.resources.values("id"),
attribute_definition=transformer.attribute_definition)
for attribute in all_resource_att:
total_produced += attribute.value
transformer.total_produced = total_produced
transformer.save()

# update total consumed
total_consumed = 0
child_transformers = Transformer.objects.filter(consume_from_attribute_definition=transformer.attribute_definition,
consume_from_resource_group=transformer.resource_group)
for child_transformer in child_transformers:
total_consumed += child_transformer.total_produced / child_transformer.factor
transformer.total_consumed = total_consumed
transformer.save()


class Migration(migrations.Migration):

dependencies = [
("resource_tracker_v2", "0005_auto_20230803_1126"),
]

operations = [
migrations.RunPython(update_all_resource_consumption),
]
3 changes: 2 additions & 1 deletion service_catalog/models/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ def reset_to_last_stable_state(self):
self.state = InstanceState.AVAILABLE

def delete_linked_resources(self):
self.resources.filter(is_deleted_on_instance_deletion=True).delete()
for resource in self.resources.filter(is_deleted_on_instance_deletion=True):
resource.delete()

@classmethod
def on_create_call_hook_manager(cls, sender, instance, created, *args, **kwargs):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,11 +214,19 @@ def test_update_resource_patch_one_attribute(self):
self.assertEqual(2, self.server1.resource_attributes.get(attribute_definition=self.memory_attribute).value)

def test_delete_resource(self):
transformer = Transformer.objects.get(attribute_definition=self.core_attribute,
resource_group=self.cluster)
available_before = transformer.available

resource_to_delete = self.server1.id
response = self.client.delete(self._details_url, format='json')
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.assertFalse(Resource.objects.filter(id=resource_to_delete).exists())

# check consumption updated
transformer.refresh_from_db()
self.assertEqual(transformer.available, available_before - 10)

def test_update_resource_group_of_resource(self):
new_rg = ResourceGroup.objects.create(name="new_rg")
data = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from resource_tracker_v2.api.serializers.resource_serializer import ResourceSerializer
from resource_tracker_v2.models import Resource
from resource_tracker_v2.models import Resource, Transformer
from tests.test_resource_tracker_v2.base_test_resource_tracker_v2 import BaseTestResourceTrackerV2API


Expand All @@ -13,18 +13,51 @@ def _validate_created(self):
self.assertEqual(self.number_resource_before + 1, Resource.objects.all().count())

def test_create_resource(self):
transformer = Transformer.objects.get(attribute_definition=self.core_attribute,
resource_group=self.cluster)
available_before = transformer.available
core_attribute_value = 10

data = {
"resource_group": self.cluster.id,
"name": "new_server",
"service_catalog_instance": None,
"is_deleted_on_instance_deletion": False,
"resource_attributes": [
{"name": "core",
"value": 10
"value": core_attribute_value
}
],
}
serializer = ResourceSerializer(data=data)
self.assertTrue(serializer.is_valid())
serializer.save()
self._validate_created()

transformer.refresh_from_db()
self.assertEqual(transformer.available, available_before + core_attribute_value)

def test_update_resource(self):
transformer = Transformer.objects.get(attribute_definition=self.core_attribute,
resource_group=self.cluster)
available_before = transformer.available
core_attribute_before = 10
new_core_attribute_value = 20

data = {
"resource_group": self.cluster.id,
"name": "new_server",
"service_catalog_instance": None,
"is_deleted_on_instance_deletion": False,
"resource_attributes": [
{"name": "core",
"value": new_core_attribute_value
}
],
}
serializer = ResourceSerializer(instance=self.server1, data=data)
self.assertTrue(serializer.is_valid())
serializer.save()
# check consumption updated
transformer.refresh_from_db()
self.assertEqual(transformer.available, available_before - core_attribute_before + new_core_attribute_value)
26 changes: 24 additions & 2 deletions tests/test_resource_tracker_v2/test_model/test_resource.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from copy import copy

from django.contrib.auth.models import User

from resource_tracker_v2.models import Transformer
from resource_tracker_v2.models.resource import Resource, InvalidAttributeDefinition
from service_catalog.models import Service, Instance, InstanceState
from tests.test_resource_tracker_v2.base_test_resource_tracker_v2 import BaseTestResourceTrackerV2
Expand Down Expand Up @@ -58,3 +57,26 @@ def test_set_attribute_on_invalid_attribute(self):
server2 = self.cluster.create_resource(name="server2")
with self.assertRaises(InvalidAttributeDefinition):
server2.set_attribute(self.vcpu_attribute, 10)

def test_transformer_consumption_updated_on_resource_delete(self):
transformer = Transformer.objects.get(attribute_definition=self.core_attribute,
resource_group=self.cluster)
available_before = transformer.available
self.server1.delete()
# check consumption updated
transformer.refresh_from_db()
self.assertEqual(transformer.available, available_before - 10)

def test_consumption_updated_on_delete_resource_linked_to_instance(self):
self._prepare_service_catalog()

transformer = Transformer.objects.get(attribute_definition=self.vcpu_attribute,
resource_group=self.single_vms)
available_before = transformer.available
self.test_instance.delete()
# check resource is deleted
self.assertFalse(Resource.objects.filter(id=self.resource_id_to_delete).exists())

# check consumption updated
transformer.refresh_from_db()
self.assertEqual(transformer.available, available_before - 5)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from django.urls import reverse

from resource_tracker_v2.models import Resource, ResourceGroup
from resource_tracker_v2.models import Resource, ResourceGroup, Transformer
from tests.test_resource_tracker_v2.base_test_resource_tracker_v2 import BaseTestResourceTrackerV2


Expand Down Expand Up @@ -42,19 +42,28 @@ def test_resource_group_resources_create(self):
f"{self.memory_attribute.name}": 20,
"is_deleted_on_instance_deletion": True
}
# Check consumption before update
transformer = Transformer.objects.get(attribute_definition=self.core_attribute,
resource_group=self.cluster)
available_before = transformer.available
core_attribute_value = 10

response = self.client.post(url, data=data)
self.assertEqual(302, response.status_code)
self.assertTrue(Resource.objects.filter(name="new_resource",
resource_group=self.cluster).exists())
target_resource = Resource.objects.get(name="new_resource",
resource_group=self.cluster)
self.assertEqual(10, target_resource.resource_attributes.
self.assertEqual(core_attribute_value, target_resource.resource_attributes.
filter(attribute_definition=self.core_attribute).first().value)
self.assertEqual(20, target_resource.resource_attributes.
filter(attribute_definition=self.memory_attribute).first().value)
self.assertEqual(0, target_resource.resource_attributes.
filter(attribute_definition=self.three_par_attribute).first().value)

transformer.refresh_from_db()
self.assertEqual(transformer.available, available_before + core_attribute_value)

def test_resource_group_resources_edit(self):
args = {
"resource_group_id": self.cluster.id,
Expand Down

0 comments on commit ac397f0

Please sign in to comment.