Add audit scoper for baremetal data model

Bare metal cluster data model was introduced in Queens cycle.
Since the model is different from compute data model, we
need add CDM scoper for bare metal cluster data model

Change-Id: Idd041cefb692085d4545252d229ebe8602926b58
Implements: blueprint audit-scoper-for-baremetal-data-model
This commit is contained in:
Yumeng_Bao 2018-09-03 04:59:29 -07:00 committed by Alexander Chadin
parent 63afd8259a
commit af0c90db4d
6 changed files with 110 additions and 4 deletions

View File

@ -0,0 +1,3 @@
---
features:
- Baremetal Model gets Audit scoper with an ability to exclude Ironic nodes.

View File

@ -21,6 +21,7 @@ from watcher.common import ironic_helper
from watcher.decision_engine.model.collector import base
from watcher.decision_engine.model import element
from watcher.decision_engine.model import model_root
from watcher.decision_engine.scope import baremetal as baremetal_scope
LOG = log.getLogger(__name__)
@ -45,7 +46,9 @@ class BaremetalClusterDataModelCollector(base.BaseClusterDataModelCollector):
return None
def get_audit_scope_handler(self, audit_scope):
return None
self._audit_scope_handler = baremetal_scope.BaremetalScope(
audit_scope, self.config)
return self._audit_scope_handler
def execute(self):
"""Build the baremetal cluster data model"""

View File

@ -193,6 +193,7 @@ class ModelBuilder(object):
re-scheduled for Pike. In the meantime, all the associated code has been
commented out.
"""
def __init__(self, osc):
self.osc = osc
self.model = model_root.ModelRoot()

View File

@ -24,11 +24,30 @@ class BaremetalScope(base.BaseScope):
super(BaremetalScope, self).__init__(scope, config)
self._osc = osc
def exclude_resources(self, resources, **kwargs):
nodes_to_exclude = kwargs.get('nodes')
for resource in resources:
if 'ironic_nodes' in resource:
nodes_to_exclude.extend(
[node['uuid'] for node
in resource['ironic_nodes']])
def remove_nodes_from_model(self, nodes_to_exclude, cluster_model):
for node_uuid in nodes_to_exclude:
node = cluster_model.get_node_by_uuid(node_uuid)
cluster_model.remove_node(node)
def get_scoped_model(self, cluster_model):
"""Leave only nodes and instances proposed in the audit scope"""
if not cluster_model:
return None
nodes_to_exclude = []
baremetal_scope = []
if not self.scope:
return cluster_model
for scope in self.scope:
baremetal_scope = scope.get('baremetal')
if baremetal_scope:
@ -37,7 +56,11 @@ class BaremetalScope(base.BaseScope):
if not baremetal_scope:
return cluster_model
# TODO(yumeng-bao): currently self.scope is always []
# Audit scoper for baremetal data model will be implemented:
# https://blueprints.launchpad.net/watcher/+spec/audit-scoper-for-baremetal-data-model
for rule in baremetal_scope:
if 'exclude' in rule:
self.exclude_resources(
rule['exclude'], nodes=nodes_to_exclude)
self.remove_nodes_from_model(nodes_to_exclude, cluster_model)
return cluster_model

View File

@ -57,3 +57,17 @@ fake_scope_3 = [{'compute': [{'host_aggregates': [{'id': '1'}]},
}]
}
]
baremetal_scope = [
{'baremetal': [
{'exclude': [
{'ironic_nodes': [
{'uuid': 'c5941348-5a87-4016-94d4-4f9e0ce2b87a'},
{'uuid': 'c5941348-5a87-4016-94d4-4f9e0ce2b87c'}
]
}
]
}
]
}
]

View File

@ -0,0 +1,62 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2018 SBCloud
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import mock
from watcher.decision_engine.scope import baremetal
from watcher.tests import base
from watcher.tests.decision_engine.model import faker_cluster_state
from watcher.tests.decision_engine.scope import fake_scopes
class TestBaremetalScope(base.TestCase):
def setUp(self):
super(TestBaremetalScope, self).setUp()
self.fake_cluster = faker_cluster_state.FakerBaremetalModelCollector()
self.audit_scope = fake_scopes.baremetal_scope
def test_exclude_all_ironic_nodes(self):
cluster = self.fake_cluster.generate_scenario_1()
baremetal.BaremetalScope(
self.audit_scope,
mock.Mock(),
osc=mock.Mock()).get_scoped_model(cluster)
self.assertEqual({}, cluster.get_all_ironic_nodes())
def test_exclude_resources(self):
nodes_to_exclude = []
resources = fake_scopes.baremetal_scope[0]['baremetal'][0]['exclude']
baremetal.BaremetalScope(
self.audit_scope, mock.Mock(), osc=mock.Mock()).exclude_resources(
resources,
nodes=nodes_to_exclude)
self.assertEqual(sorted(nodes_to_exclude),
sorted(['c5941348-5a87-4016-94d4-4f9e0ce2b87a',
'c5941348-5a87-4016-94d4-4f9e0ce2b87c']))
def test_remove_nodes_from_model(self):
cluster = self.fake_cluster.generate_scenario_1()
baremetal.BaremetalScope(
self.audit_scope,
mock.Mock(),
osc=mock.Mock()).remove_nodes_from_model(
['c5941348-5a87-4016-94d4-4f9e0ce2b87a'],
cluster)
self.assertEqual(len(cluster.get_all_ironic_nodes()), 1)