def _eval_expression(self, expression, node_id, ns={}): ephemeral_api = db_api.ephemeral_api_from_api(api) builder = ast.FilterBuilder(ast.FilterTokenizer(), expression, api=ephemeral_api) node = ephemeral_api._model_get_by_id('nodes', node_id) builder.eval_node(node, symbol_table=ns) new_node = ephemeral_api._model_get_by_id('nodes', node_id) return new_node
def _safely_run_plan(self, plan, node_id, expect_backend_fail=False): node = self._model_get_by_id('nodes', node_id) api = self.api if expect_backend_fail is True: api = db_api.ephemeral_api_from_api(self.api) self.logger.debug('applying plan: %s' % plan) for step in plan: primitive = step['primitive'] ns = {} if 'ns' in step: ns = step['ns'] self.logger.debug('safe-running primitive %s' % primitive) if not '.' in primitive: # is a run_task... see if there are any consequences actions = node['attrs'].get('opencenter_agent_actions', {}) if primitive in actions: consequences = actions[primitive].get('consequences', []) for consequence in consequences: concrete_expression = self.api.concrete_expression( consequence, ns) api.apply_expression(node_id, concrete_expression) pass else: if primitive != 'chef-client.converge_chef': f = opencenter.backends.primitive_by_name(primitive) result = f({}, api, node_id, **ns) self.assertTrue('result_code' in result) if expect_backend_fail is False: self.logger.debug(result['result_str']) self.assertEqual(result['result_code'], 0) else: if result['result_code'] != 0: return if expect_backend_fail: raise AssertionError('Backend did not fail as expected')
def __init__(self, api, node_id, constraints, parent=None, prim=None, ns=None, applied_consequences=None): self.constraints = copy.deepcopy([api.regularize_expression(x) for x in constraints]) self.node_id = node_id self.base_api = api self.applied_consequences = copy.deepcopy(applied_consequences) if \ applied_consequences is not None else [] self.children = [] classname = self.__class__.__name__.lower() self.logger = logging.getLogger('%s.%s' % (__name__, classname)) self.parent = parent self.prim = prim self.task_primitives = {} self.adventures = [] self.ns = ns if ns is not None else {} self.logger.info('New solver for constraints %s' % constraints) self.logger.info('With applied constraints %s' % applied_consequences) # roll the applied consequences forward in an ephemeral # api, and do our resolution from that. self.api = db_api.ephemeral_api_from_api(self.base_api) pre_node = self.api._model_get_by_id('nodes', self.node_id) for consequence in self.applied_consequences: node = self.api._model_get_by_id('nodes', self.node_id) ast.apply_expression(node, consequence, self.api) # get rid of constraints we've already solved self.constraints = [x for x in self.constraints if not self._constraint_satisfied(x)] node = self.api._model_get_by_id('nodes', self.node_id) # grab the tasks published from this node as possible primitives # ... # we aren't actually solving through tasks and adventures # yet, but likely have the need if 'opencenter_agent_actions' in node['attrs'] and \ 'backends' in node['facts'] and \ 'agent' in node['facts']['backends']: for task_name in node['attrs']['opencenter_agent_actions']: mangled_name = task_name task = node['attrs']['opencenter_agent_actions'][task_name] id = hash(mangled_name) & 0xFFFFFFFF # should verify this unique against backends self.task_primitives[id] = {} self.task_primitives[id]['id'] = id self.task_primitives[id]['name'] = mangled_name self.task_primitives[id]['task_name'] = task_name self.task_primitives[id]['constraints'] = \ task['constraints'] self.task_primitives[id]['consequences'] = \ task['consequences'] self.task_primitives[id]['args'] = task['args'] self.task_primitives[id]['weight'] = 50 self.task_primitives[id]['timeout'] = task['timeout'] if \ 'timeout' in task else 30 self.logger.debug('Node before applying consequences: %s' % pre_node) self.logger.debug('Applied consequences: %s' % self.applied_consequences) # ephemeral_node = self.api._model_get_by_id('nodes', self.node_id) self.logger.debug('Node after applying consequences: %s' % node)