Example #1
0
    def _load_unit(self, u):
        verb(2, "Loading data for unit " + str(u))
        name = u.name
        #print("Load "+name)
        if name not in self.deferred:
            #print("Already loaded")
            return u
        lazy = set()
        for kind in self.processing:
            flip = kind in [Unit.AFTER, Unit.REQUIRES]
            #ep("Processing relationship "+kind)

            other_names = self.backend.unit_property(name, kind) or []
            for other in other_names:
                if not other:
                    continue
                if kind == Unit.MOUNTS:
                    other = 'GEN-' + other.lstrip('/').replace('/',
                                                               '-') + '.mount'
                    #ep("Mapping RequiresMountsFor to new mount unit " + other)
                ou = self._unit(other)
                lazy.add(ou)
                u.add_relationship(kind, ou)
        u.loaded = True
        self.deferred.remove(name)
        for z in lazy:
            self._load_unit(z)
        return u
Example #2
0
 def vf(data, iteration, origin, steps):
     if data.nid in record.visited:
         verb("This node was already visited.")
         return False
     verb("This node not visited yet.")
     record.visited.append(data.nid)
     record.origins[data.nid] = origin
     return True
Example #3
0
 def unit_property(self, name, kind):
     escaped_name = [ '--', name ] if name.startswith('-') else [ name ]
     verb(2, "Escaped name for '{}' is {}".format(str(name), pformat(escaped_name)))
     result = self._capture(LiveBackend.SHOW_PROPERTY + [ kind ] + escaped_name)
     if result:
         other_names = result[0].strip().split(' ')
         if len(other_names) > 1 or other_names[0] != '':
             return other_names
     return []
Example #4
0
def test_visit_node():
    v, g, record = new_visitor(data={'a-c': 'ac', 'b-a': 'ba'}, sorting=True)
    a = g.node('a')
    b = g.node('b')
    c = g.node('c')
    assert None not in [a, b, c]
    v.Visit()

    verb(pformat(record))
    assert record.origins['c'] == a
    assert record.origins['b'] is None
Example #5
0
    def Visit(self):
        self.init_data()

        # NOTE the set of nodes to visit is used like this
        # because it can grow during the visiting, if new nodes are discovered.
        iteration = 0
        while len(self.to_visit):
            nid = self.to_visit.pop()
            data = self.datas[nid]
            iteration += 1
            verb("Visiting {} with iteration = {} step 0 from nowhere".format(
                data.nid, iteration))
            self.visit_node(data, iteration, None, 0)
        return self.datas
Example #6
0
    def search(self, kinds, prune=None):
        for u in self.Units():
            u = self.Unit(u.name)

        all_set = False
        statuses = set()
        name_matchers = []
        for k in kinds:
            if k == 'all':
                all_set = True
            elif k in Unit.STATUS:
                statuses.add(k)
            else:
                ep("Adding name matcher " + str(k))
                name_matchers.append(k)

        startwith = set()
        if all_set:
            verb("All units selected as a starting point")
            for u in self.Units():
                startwith.add(u.name)
        else:
            ep("Searching " + str(len(self.Units())) + " with " +
               str(len(name_matchers)) + " name matchers")
            for u in self.Units():
                for nm in name_matchers:
                    if re.search(nm, u.name):
                        ep("matched " + u.name)
                        startwith.add(u.name)
                        break
                    elif u.name.startswith("test-loop"):
                        ep("matcher " + str(nm) + " did not match " + u.name)
                    #else:
                    #    ep("non test-loop")
        verb2("Starting with a set of units:" + pformat(startwith))
        if statuses:
            filterout = set()
            verb("Excluding units that do not match statuses " +
                 pformat(statuses))
            for u in self.Units():
                if not u.status_match(statuses):
                    filterout.add(u.name)
            startwith = startwith - filterout

        if prune:
            filterout = set()
            verb("Excluding units that do not match names " + pformat(prune))
            for u in self.Units():
                for nm in prune:
                    if re.search(nm, u.name):
                        filterout.add(u.name)
                        break
            startwith = startwith - filterout

        return [self.Unit(x) for x in startwith]
Example #7
0
    def visit_node(self, data, iteration, origin, steps):
        nid = data.nid
        n = data.n

        # start with this node and visit it
        #verb(f"here, nid={nid}, n={n}, iter={iteration}, origin={origin}")

        visit_further = self.visit_func(data, iteration, origin, steps)

        # Note that iteration and origin are set *after* the visit function,
        # however the visit function receives those in the function call,
        # it is not set yet in the object so that the visitor an check if there
        # is a pre-existing value. However it is set prior to moving on to the
        # next node, so that the historical value is maintained
        data.i = iteration
        data.o = origin

        visit_also = []
        if not visit_further:
            verb("Will not visit further from node " + str(nid))
        if visit_further:
            #verb(f"Node {nid} - checking edges.")
            for e in n.Edges():
                verb("Edge {}".format(e))
                if e.b.id == nid:
                    if e.a.id == nid:
                        log.warning("self-loop")
                    else:
                        log.warning("Back-to-front edge!")
                        visit_also.append(e.a.id())
                else:
                    visit_also.append(e.b.id())

            if not visit_also:
                verb("{} is terminal or visitor returned False.".format(nid))
            else:
                verb("Will visit {} nodes from here".format(len(visit_also)))
                if self.sorting:
                    visit_also = sorted(visit_also)
                verb("  Will visit also " + ", ".join(visit_also))

            for vid in visit_also:
                if vid is not None:
                    vdata = data.d.get(vid, None)
                    if not vdata:
                        verb(
                            "****BUG***** visitor data for {} not yet initialised - edge to un-indexed node, Creating it."
                            .format(vid))
                        vdata = self.init_node(nid=vid)
                    data.v = vdata
                    self.visit_node(vdata, iteration, n, steps + 1)
                data.v = None
Example #8
0
    def Graph(self, name, backwards=True, units=None):
        if name is None:
            name = "systemd"

        g = Graph(name)
        ep("Generating graph for " + str(len(units)) + " selected units")
        # First preprocess the units to pre-load and generate extras if required

        if units is None:
            units = self.Units()

        todo = set()
        done = set()
        for u in units:
            u = self.Unit(u.name)
            todo.add(u.name)

        # It is simple to go forwards, just follow the edges
        if not backwards:
            while len(todo):
                #ep("TODO: "+str(len(todo)))
                uname = todo.pop()
                if uname in done:
                    #ep("Aldready done")
                    continue

                u = self.Unit(uname)
                #ep("Add node " + u.name + " with " + str(len(u.Edges())) + " edges")
                g.add_node(u)
                done.add(uname)

                for e in u.Edges():
                    #ep("Check edge " + str(e))
                    a = e.a
                    b = e.b
                    if e.a.name not in done:
                        todo.add(e.a.name)

                    if e.b.name not in done:
                        todo.add(e.b.name)
                    #ep("Add edge " + str(e))
                    g.add_edge(e)

        else:
            #ep("Search network for forward links to these nodes")
            # we are going backwards, need to search the entire set of nodes
            # for forward edges that point to these nodes.
            while len(todo):
                verb("TODO: " + str(len(todo)))
                uname = todo.pop()
                if uname in done:
                    continue
                u = self.Unit(uname)
                g.add_node(u)
                done.add(uname)
                for u2 in self.Units():
                    verb("Search for units with edges going to " + uname)
                    if u2.name == uname:
                        continue
                    elif u2.name in done:
                        continue
                    elif u2.name in todo:
                        # do it later
                        continue
                    else:
                        for e in u2.Edges():
                            b = e.b
                            if b.name == uname:
                                aname = e.a.name
                                if aname not in todo and aname not in done:
                                    g.add_node(self.Unit(aname))
                                    g.add_edge(e)
                                    #ep("Add edge " + str(e))
                                    todo.add(aname)

            # Now we will have all interesting nodes in 'done'
        return g