Beispiel #1
0
    def add_backend(self, state_data, api, node_id, **kwargs):
        reply_data = {}

        self.logger.debug('adding backend %s', kwargs['backend'])

        old_node = api._model_get_by_id('nodes', node_id)
        old_backend = old_node['facts'].get('backends', [])

        reply_data['rollback'] = {'primitive': 'node.set_fact',
                                  'ns': {'key': 'backends',
                                         'value': old_backend}}

        opencenter.webapp.ast.apply_expression(
            node_id, 'facts.backends := union(facts.backends, "%s")' %
            kwargs['backend'], api)

        return self._ok(data=reply_data)
Beispiel #2
0
    def additional_constraints(self, api, node_id, action, ns):
        if action == 'set_fact':
            addl_constraints = []

            if not 'key' in ns:
                raise ValueError('no key in ns')
            key = ns['key']

            # see what backend this key is in...
            for name, obj in backends.backend_objects.iteritems():
                if key in obj.facts:
                    # we can only solve for settable facts.  If the
                    # fact is not settable, then there is likely (HAS TO BE!)
                    # a primitive to set this somewhere else.  Probably in
                    # the same backend.
                    fact_info = obj.facts[key]
                    if fact_info['settable'] is not True:
                        return None

                    addl_constraints.append('"%s" in facts.backends' % name)
                    # if fact_info['converge']:
                    #     addl_constraints.append('facts.converged = true')
                    return addl_constraints
            return None

        if action == 'unapply_fact':
            if not 'key' in ns:
                raise ValueError('no key in ns')

            key = ns['key']

            addl_constraints = []

            for name, obj in backends.backend_objects.iteritems():
                if key in obj.facts:
                    # we can only solve for settable facts.  If the
                    # fact is not settable, then there is likely (HAS TO BE!)
                    # a primitive to set this somewhere else.  Probably in
                    # the same backend.
                    addl_constraints.append('"%s" in facts.backends' % name)
                    fact_info = obj.facts[key]
                    if fact_info['converge'] is True:
                        addl_constraints.append('facts.converged = true')

                    return addl_constraints
            return None

        if action == 'apply_fact':
            if not 'key' in ns:
                raise ValueError('no key in ns')
            key = ns['key']

            addl_constraints = []
            # see what backend this key is in...
            for name, obj in backends.backend_objects.iteritems():
                if key in obj.facts:
                    # we can only solve for settable facts.  If the
                    # fact is not settable, then there is likely (HAS TO BE!)
                    # a primitive to set this somewhere else.  Probably in
                    # the same backend.
                    addl_constraints.append('"%s" in facts.backends' % name)
                    fact_info = obj.facts[key]
                    if fact_info['converge'] is True:
                        addl_constraints.append('facts.converged = true')

                    return addl_constraints
            return None

        if action == 'add_backend':
            if ns['backend'] == 'node':
                return []

            if opencenter.backends.primitive_by_name(
                    '%s.add_backend' % ns['backend']) is None:
                return []
            else:
                return None

        if action == 'set_parent':
            new_constraints = []

            if not 'parent' in ns:
                raise ValueError('no parent set')
            parent = api._model_get_by_id('nodes', ns['parent'])
            if 'container' in parent['facts'].get('backends', {}):
                # should already be the case, but...
                new_constraints.append('"node" in facts.backends')

                existing_node = api._model_get_by_id('nodes', node_id)
                if existing_node.get('attrs', {}).get('locked', False):
                    # Node is locked, set_parent not allowed.
                    return None
                if parent.get('attrs', {}).get('locked', False):
                    # parent is locked
                    return None

                ephemeral_api = opencenter.db.api.ephemeral_api_from_api(api)
                opencenter.webapp.ast.apply_expression(existing_node,
                                                       'facts.parent_id :='
                                                       '"%s"' %
                                                       parent['id'],
                                                       ephemeral_api)

                proposed_node = ephemeral_api._model_get_by_id('nodes',
                                                               node_id)

                self.logger.debug('Setting parent would change %s to %s' %
                                  (existing_node, proposed_node))

                # this should be much smarter.  losing vs gaining,
                # and add/remove facts as appropriate.
                all_keys = set(existing_node['facts'].keys() +
                               proposed_node['facts'].keys())
                changed_facts = []

                for key in all_keys:
                    if existing_node['facts'].get(key, None) != \
                            proposed_node['facts'].get(key, None):
                        changed_facts.append(key)

                self.logger.debug('Changed facts: %s' % changed_facts)

                required_facts = []
                for key in changed_facts:
                    action = 'unapply_fact'
                    value = None

                    if key in proposed_node['facts']:
                        action = 'unapply_fact'
                        value = proposed_node['facts'][key]

                    # run this through the fact discovery
                    new_fact_reqs = self.additional_constraints(
                        api, node_id, action, {'key': key,
                                               'value': value})

                    if new_fact_reqs is None:
                        self.logger.debug('Impossible to satisfy %s->%s' %
                                          (key, value))
                        return None

                    for fact in new_fact_reqs:
                        if not fact in new_constraints:
                            new_constraints.append(fact)

                self.logger.debug('Required facts: %s' % required_facts)
                return new_constraints

                # parent_facts = api._model_get_by_id('nodes', parent)

                # determine what facts are going to be inherited,
                # so we can run the 'set_fact' (apply fact?)
                # node differ?
                # inherited_facts = parent['facts'].get('inherited', {})
                # return ['facts.%s="%s"' % (k, v)
                #         for k, v in inherited_facts.items()]
            else:
                # cannot set_parent to something that isn't a container
                return None
        return []