3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
16 from cmframework.utils import cmactivationwork
17 from cmframework.server import cmeventletrwlock
18 from cmframework.server import cmcsn
19 from cmframework.server import cmsnapshot
20 from cmframework.utils.cmflagfile import CMFlagFile
21 from cmframework.utils import cmalarm
24 class CMProcessor(object):
25 SERVICE_GROUP_NAME = 'config-manager'
32 activationstate_handler,
34 logging.debug('CMProcessor constructed')
36 self.backend_handler = backend_handler
37 self.lock = cmeventletrwlock.CMEventletRWLock()
38 self.csn = cmcsn.CMCSN(self.backend_handler)
39 self.validator = validator
40 self.activator = activator
41 self.reboot_requests = set()
42 self.automatic_activation_disabled = CMFlagFile('automatic_activation_disabled')
43 self.changemonitor = changemonitor
44 self.activationstate_handler = activationstate_handler
45 self.snapshot = cmsnapshot.CMSnapshot(snapshot_handler)
47 def reboot_request(self, node_name):
48 logging.debug('reboot_request called for %s', node_name)
50 self.reboot_requests.add(node_name)
52 def _clear_reboot_requests(self):
53 logging.debug('_clear_reboot_requests called')
55 self.reboot_requests.clear()
57 def _raise_reboot_alarms(self):
58 logging.debug('_raise_reboot_alarms called')
60 reboot_request_alarm = cmalarm.CMRebootRequestAlarm()
62 for node_name in self.reboot_requests:
63 reboot_request_alarm.raise_alarm_for_node(node_name)
65 def get_property(self, prop_name, snapshot_name=None):
66 logging.debug('get_property called for %s', prop_name)
68 with self.lock.reader():
70 self.snapshot.load(snapshot_name)
72 return self.snapshot.get_property(prop_name)
74 return self.backend_handler.get_property(prop_name)
76 def get_properties(self, prop_filter, snapshot_name=None):
77 logging.debug('get_properties called with filter %s', prop_filter)
79 with self.lock.reader():
81 self.snapshot.load(snapshot_name)
83 return self.snapshot.get_properties(prop_filter)
85 return self.backend_handler.get_properties(prop_filter)
87 def set_property(self, prop_name, prop_value):
88 logging.debug('set_property called %s=%s', prop_name, prop_value)
91 props[prop_name] = prop_value
92 return self.set_properties(props)
94 def set_properties(self, props, overwrite=False):
95 logging.debug('set_properties called for %s', str(props))
97 with self.lock.writer():
98 self._validate_set(props)
100 logging.debug('Deleting old configuration data as requested')
101 orig_props = self.backend_handler.get_properties('.*')
102 self.backend_handler.delete_properties(orig_props.keys())
103 self.backend_handler.set_properties(props)
106 if not self.automatic_activation_disabled:
107 return self._activate_set(props)
111 def delete_property(self, prop_name):
112 logging.debug('delete_property called for %s', prop_name)
115 props.append(prop_name)
116 return self._delete_properties(props, None)
118 def delete_properties(self, arg):
119 logging.debug('delete_properties called with arg %r', arg)
123 if isinstance(arg, str):
125 props = self.get_properties(prop_filter)
129 return self._delete_properties(keys, prop_filter)
131 def _delete_properties(self, props, props_filter):
132 logging.debug('_delete_properties called with props %s filter %s', props, props_filter)
134 with self.lock.writer():
135 self._validate_delete(props)
137 self.backend_handler.delete_properties(props_filter)
140 self.backend_handler.delete_property(props[0])
142 self.backend_handler.delete_properties(props)
145 if not self.automatic_activation_disabled:
146 return self._activate_delete(props)
150 def _validate_set(self, props):
151 logging.debug('_validate_set called for %s', str(props))
153 self.validator.validate_set(props)
155 def _activate_set_no_lock(self, props):
156 logging.debug('_activate_set_no_lock called for %s', str(props))
158 uuid_value = self.changemonitor.start_change()
160 work = cmactivationwork.CMActivationWork(cmactivationwork.CMActivationWork.OPER_SET,
161 self.csn.get(), props)
162 work.uuid_value = uuid_value
163 self.activator.add_work(work)
166 def _activate_set(self, props):
167 logging.debug('_activate_set called')
169 with self.lock.reader():
170 return self._activate_set_no_lock(props)
172 def _validate_delete(self, props):
173 logging.debug('_validate_delete called for %s', str(props))
175 self.validator.validate_delete(props)
177 def _activate_delete(self, props):
178 logging.debug('_activate_delete called for %s', str(props))
180 with self.lock.reader():
181 uuid_value = self.changemonitor.start_change()
182 work = cmactivationwork.CMActivationWork(cmactivationwork.CMActivationWork.OPER_DELETE,
183 self.csn.get(), props)
184 work.uuid_value = uuid_value
185 self.activator.add_work(work)
188 def create_snapshot(self, snapshot_name):
189 logging.debug('create_snapshot called, snapshot name is %s', snapshot_name)
191 with self.lock.writer():
192 self.snapshot.create(snapshot_name, self.backend_handler)
194 def restore_snapshot(self, snapshot_name):
195 logging.debug('restore_snapshot called, snapshot name is %s', snapshot_name)
197 with self.lock.writer():
198 self.snapshot.load(snapshot_name)
200 self._validate_set(self.snapshot.get_properties())
202 self.snapshot.restore(self.backend_handler)
204 self.csn = cmcsn.CMCSN(self.backend_handler)
206 self._activate_set_no_lock(self.snapshot.get_properties())
208 def list_snapshots(self):
209 logging.debug('list_snapshots called')
212 with self.lock.writer():
213 snapshots = self.snapshot.list()
217 def delete_snapshot(self, snapshot_name):
218 logging.debug('delete_snapshot called, snapshot name is %s', snapshot_name)
220 with self.lock.writer():
221 self.snapshot.delete(snapshot_name)
223 def activate(self, node_name=None, startup_activation=False):
224 logging.debug('activate called, node is %s', node_name)
226 activation_alarm = cmalarm.CMActivationFailedAlarm()
228 activation_alarm.cancel_alarm_for_node(node_name)
230 activation_alarm.cancel_alarm_for_sg(CMProcessor.SERVICE_GROUP_NAME)
232 with self.lock.reader():
233 uuid_value = self.changemonitor.start_change()
235 work = cmactivationwork.CMActivationWork(
236 cmactivationwork.CMActivationWork.OPER_FULL,
237 self.csn.get(), {}, None, startup_activation)
239 work = cmactivationwork.CMActivationWork(
240 cmactivationwork.CMActivationWork.OPER_FULL,
241 self.csn.get(), {}, node_name)
242 work.uuid_value = uuid_value
243 self.activator.add_work(work)
245 logging.debug('activation work added, going to wait for result')
246 failures = work.get_result()
247 logging.debug('got activation result')
249 if self.reboot_requests:
250 self._raise_reboot_alarms()
253 self.activationstate_handler.clear_full_failed()
256 logging.warning('Activation failed: %s', failures)
258 failed_activators = [activator for handler in failures.keys()
259 for activator in failures[handler]]
261 supplementary_info = {'failed activators': failed_activators}
264 activation_alarm.raise_alarm_for_node(node_name, supplementary_info)
266 self.activationstate_handler.set_full_failed(failed_activators)
268 activation_alarm.raise_alarm_for_sg(CMProcessor.SERVICE_GROUP_NAME,
272 def activate_node(self, node_name):
273 logging.debug('activate_node called, node name is %s', node_name)
275 if self.automatic_activation_disabled:
278 with self.lock.reader():
279 node_csn = self.csn.get_node_csn(node_name)
281 if self.csn.get() == node_csn:
282 logging.info('No change in data since last translation, last csn %d',
286 self._clear_reboot_requests()
287 work = cmactivationwork.CMActivationWork(cmactivationwork.CMActivationWork.OPER_NODE,
288 self.csn.get(), {}, node_name)
289 self.activator.add_work(work)
291 activation_alarm = cmalarm.CMActivationFailedAlarm()
292 activation_alarm.cancel_alarm_for_node(node_name)
294 failures = work.get_result()
296 logging.warning('Activation failed: %s', failures)
298 failed_activators = [activator for handler in failures.keys()
299 for activator in failures[handler]]
300 supplementary_info = {'failed activators': failed_activators}
301 activation_alarm.raise_alarm_for_node(node_name, supplementary_info)
304 with self.lock.writer():
305 self.csn.sync_node_csn(node_name)
307 return node_name in self.reboot_requests
309 def set_automatic_activation_state(self, state):
310 logging.debug('set_automatic_activation_state called, state is %s', state)
312 with self.lock.writer():
314 self.automatic_activation_disabled.unset()
316 self.automatic_activation_disabled.set()