Coverage for watcher/decision_engine/model/collector/ironic.py: 48%

46 statements  

« prev     ^ index     » next       coverage.py v7.8.2, created at 2025-06-17 12:22 +0000

1# -*- encoding: utf-8 -*- 

2# Copyright (c) 2017 ZTE Corporation 

3# 

4# Authors:Yumeng Bao <bao.yumeng@zte.com.cn> 

5# 

6# Licensed under the Apache License, Version 2.0 (the "License"); 

7# you may not use this file except in compliance with the License. 

8# You may obtain a copy of the License at 

9# 

10# http://www.apache.org/licenses/LICENSE-2.0 

11# 

12# Unless required by applicable law or agreed to in writing, software 

13# distributed under the License is distributed on an "AS IS" BASIS, 

14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

15# See the License for the specific language governing permissions and 

16# limitations under the License. 

17 

18from oslo_log import log 

19 

20from watcher.common import ironic_helper 

21from watcher.decision_engine.model.collector import base 

22from watcher.decision_engine.model import element 

23from watcher.decision_engine.model import model_root 

24from watcher.decision_engine.scope import baremetal as baremetal_scope 

25 

26LOG = log.getLogger(__name__) 

27 

28 

29class BaremetalClusterDataModelCollector(base.BaseClusterDataModelCollector): 

30 """Baremetal cluster data model collector 

31 

32 The Baremetal cluster data model collector creates an in-memory 

33 representation of the resources exposed by the baremetal service. 

34 """ 

35 

36 def __init__(self, config, osc=None): 

37 super(BaremetalClusterDataModelCollector, self).__init__(config, osc) 

38 

39 @property 

40 def notification_endpoints(self): 

41 """Associated notification endpoints 

42 

43 :return: Associated notification endpoints 

44 :rtype: List of :py:class:`~.EventsNotificationEndpoint` instances 

45 """ 

46 return None 

47 

48 def get_audit_scope_handler(self, audit_scope): 

49 self._audit_scope_handler = baremetal_scope.BaremetalScope( 

50 audit_scope, self.config) 

51 if self._data_model_scope is None or ( 

52 len(self._data_model_scope) > 0 and ( 

53 self._data_model_scope != audit_scope)): 

54 self._data_model_scope = audit_scope 

55 self._cluster_data_model = None 

56 LOG.debug("audit scope %s", audit_scope) 

57 return self._audit_scope_handler 

58 

59 def execute(self): 

60 """Build the baremetal cluster data model""" 

61 LOG.debug("Building latest Baremetal cluster data model") 

62 

63 if self._audit_scope_handler is None: 63 ↛ 64line 63 didn't jump to line 64 because the condition on line 63 was never true

64 LOG.debug("No audit, Don't Build Baremetal data model") 

65 return 

66 if self._data_model_scope is None: 66 ↛ 70line 66 didn't jump to line 70 because the condition on line 66 was always true

67 LOG.debug("No audit scope, Don't Build Baremetal data model") 

68 return 

69 

70 builder = BareMetalModelBuilder(self.osc) 

71 return builder.execute(self._data_model_scope) 

72 

73 

74class BareMetalModelBuilder(base.BaseModelBuilder): 

75 """Build the graph-based model 

76 

77 This model builder adds the following data" 

78 

79 - Baremetal-related knowledge (Ironic) 

80 """ 

81 

82 def __init__(self, osc): 

83 self.osc = osc 

84 self.model = model_root.BaremetalModelRoot() 

85 # TODO(lpetrut): add MAAS support 

86 self.ironic_helper = ironic_helper.IronicHelper(osc=self.osc) 

87 

88 def add_ironic_node(self, node): 

89 # Build and add base node. 

90 ironic_node = self.build_ironic_node(node) 

91 self.model.add_node(ironic_node) 

92 

93 def build_ironic_node(self, node): 

94 """Build a Baremetal node from a Ironic node 

95 

96 :param node: A ironic node 

97 :type node: :py:class:`~ironicclient.v1.node.Node` 

98 """ 

99 # build up the ironic node. 

100 node_attributes = { 

101 "uuid": node.uuid, 

102 "power_state": node.power_state, 

103 "maintenance": node.maintenance, 

104 "maintenance_reason": node.maintenance_reason, 

105 "extra": {"compute_node_id": node.extra.compute_node_id} 

106 } 

107 

108 ironic_node = element.IronicNode(**node_attributes) 

109 return ironic_node 

110 

111 def execute(self, model_scope): 

112 # TODO(Dantali0n): Use scope to limit size of model 

113 for node in self.call_retry(self.ironic_helper.get_ironic_node_list): 

114 self.add_ironic_node(node) 

115 return self.model