diff --git a/watcher/decision_engine/model/element/instance.py b/watcher/decision_engine/model/element/instance.py index ebdb16d7b..c68841f76 100644 --- a/watcher/decision_engine/model/element/instance.py +++ b/watcher/decision_engine/model/element/instance.py @@ -42,6 +42,9 @@ class InstanceState(enum.Enum): class Instance(compute_resource.ComputeResource): fields = { + # If the resource is excluded by the scope, + # 'watcher_exclude' property will be set True. + "watcher_exclude": wfields.BooleanField(default=False), "state": wfields.StringField(default=InstanceState.ACTIVE.value), "memory": wfields.NonNegativeIntegerField(), diff --git a/watcher/decision_engine/scope/compute.py b/watcher/decision_engine/scope/compute.py index 41a4028e4..bfe0b729e 100644 --- a/watcher/decision_engine/scope/compute.py +++ b/watcher/decision_engine/scope/compute.py @@ -36,6 +36,12 @@ class ComputeScope(base.BaseScope): node = cluster_model.get_node_by_uuid(node_name) cluster_model.delete_instance(instance, node) + def update_exclude_instance(self, cluster_model, instance, node_name): + node = cluster_model.get_node_by_uuid(node_name) + cluster_model.unmap_instance(instance, node) + instance.update({"watcher_exclude": True}) + cluster_model.map_instance(instance, node) + def _check_wildcard(self, aggregate_list): if '*' in aggregate_list: if len(aggregate_list) == 1: @@ -108,8 +114,9 @@ class ComputeScope(base.BaseScope): self.remove_instance(cluster_model, instance, node_uuid) cluster_model.remove_node(node) - def remove_instances_from_model(self, instances_to_remove, cluster_model): - for instance_uuid in instances_to_remove: + def update_exclude_instance_in_model( + self, instances_to_exclude, cluster_model): + for instance_uuid in instances_to_exclude: try: node_name = cluster_model.get_node_by_instance_uuid( instance_uuid).uuid @@ -119,7 +126,7 @@ class ComputeScope(base.BaseScope): " instance was hosted on.", instance_uuid) continue - self.remove_instance( + self.update_exclude_instance( cluster_model, cluster_model.get_instance_by_uuid(instance_uuid), node_name) @@ -165,7 +172,7 @@ class ComputeScope(base.BaseScope): nodes=nodes_to_exclude, instance_metadata=instance_metadata) - instances_to_remove = set(instances_to_exclude) + instances_to_exclude = set(instances_to_exclude) if allowed_nodes: nodes_to_remove = set(model_hosts) - set(allowed_nodes) nodes_to_remove.update(nodes_to_exclude) @@ -174,8 +181,9 @@ class ComputeScope(base.BaseScope): if instance_metadata and self.config.check_optimize_metadata: self.exclude_instances_with_given_metadata( - instance_metadata, cluster_model, instances_to_remove) + instance_metadata, cluster_model, instances_to_exclude) - self.remove_instances_from_model(instances_to_remove, cluster_model) + self.update_exclude_instance_in_model(instances_to_exclude, + cluster_model) return cluster_model diff --git a/watcher/tests/decision_engine/scope/test_compute.py b/watcher/tests/decision_engine/scope/test_compute.py index 33d22eaa9..f3b01556a 100644 --- a/watcher/tests/decision_engine/scope/test_compute.py +++ b/watcher/tests/decision_engine/scope/test_compute.py @@ -242,16 +242,22 @@ class TestComputeScope(base.TestCase): ('INSTANCE_7', 'Node_4')] self.assertEqual(sorted(expected_edges), sorted(model.edges())) - def test_remove_instances_from_model(self): + def test_update_exclude_instances_in_model(self): model = self.fake_cluster.generate_scenario_1() compute.ComputeScope([], mock.Mock(), - osc=mock.Mock()).remove_instances_from_model( + osc=mock.Mock()).update_exclude_instance_in_model( ['INSTANCE_1', 'INSTANCE_2'], model) expected_edges = [ ('INSTANCE_0', 'Node_0'), + ('INSTANCE_1', 'Node_0'), + ('INSTANCE_2', 'Node_1'), ('INSTANCE_3', 'Node_2'), ('INSTANCE_4', 'Node_2'), ('INSTANCE_5', 'Node_2'), ('INSTANCE_6', 'Node_3'), ('INSTANCE_7', 'Node_4')] self.assertEqual(sorted(expected_edges), sorted(model.edges())) + self.assertFalse( + model.get_instance_by_uuid('INSTANCE_0').watcher_exclude) + self.assertTrue( + model.get_instance_by_uuid('INSTANCE_1').watcher_exclude)