Merge "Add audit scoper for baremetal data model"

This commit is contained in:
Zuul 2018-12-17 01:48:10 +00:00 committed by Gerrit Code Review
commit e3c5151a16
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.collector import base
from watcher.decision_engine.model import element from watcher.decision_engine.model import element
from watcher.decision_engine.model import model_root from watcher.decision_engine.model import model_root
from watcher.decision_engine.scope import baremetal as baremetal_scope
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
@ -45,7 +46,9 @@ class BaremetalClusterDataModelCollector(base.BaseClusterDataModelCollector):
return None return None
def get_audit_scope_handler(self, audit_scope): 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): def execute(self):
"""Build the baremetal cluster data model""" """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 re-scheduled for Pike. In the meantime, all the associated code has been
commented out. commented out.
""" """
def __init__(self, osc): def __init__(self, osc):
self.osc = osc self.osc = osc
self.model = model_root.ModelRoot() self.model = model_root.ModelRoot()

View File

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