summaryrefslogtreecommitdiffstats
path: root/statemachine.py
diff options
context:
space:
mode:
authorCasey Dahlin <cdahlin@redhat.com>2008-12-21 22:19:24 -0500
committerCasey Dahlin <cdahlin@redhat.com>2008-12-21 22:19:24 -0500
commit8e1ee8d111b0ec5d7bf6b9e8f1dda833e35d30f2 (patch)
treefee7aeb3627ba22a6e79b1e9717601ba7c201ba6 /statemachine.py
parent5bfc8cdfd0643425ed99cfc788a198540b8b8823 (diff)
downloadupstate-8e1ee8d111b0ec5d7bf6b9e8f1dda833e35d30f2.tar.gz
upstate-8e1ee8d111b0ec5d7bf6b9e8f1dda833e35d30f2.tar.xz
upstate-8e1ee8d111b0ec5d7bf6b9e8f1dda833e35d30f2.zip
Reorganize code into separate files
Diffstat (limited to 'statemachine.py')
-rw-r--r--statemachine.py99
1 files changed, 99 insertions, 0 deletions
diff --git a/statemachine.py b/statemachine.py
new file mode 100644
index 0000000..5c396eb
--- /dev/null
+++ b/statemachine.py
@@ -0,0 +1,99 @@
+__docformat__ = 'restructuredtext'
+
+from category import Category
+
+class StateMachine:
+ """
+ The state machine contains a list of dependencies between states, and a list
+ of states which are "up."
+ """
+
+ def __init__(self):
+ """
+ Create a new state machine
+ """
+ self.holds = {}
+ self.deps = []
+
+ def assert_state(self, cat):
+ """
+ Move states in the given Category `cat` from down to up.
+ """
+ found = None
+ for dependency in self.get_applicable_deps(cat):
+ res = self.get_satisfied_states(cat, dependency)
+ if len(res) == 0:
+ return False
+ if found == None:
+ found = res
+ else:
+ found = self.intersect_list(found, res)
+ if found == None:
+ self.add_hold(cat)
+ return True
+ if len(found) == 0:
+ return False
+ for x in found:
+ self.add_hold(x)
+ return True
+
+ def intersect_list(self, cats1, cats2):
+ """
+ Given two lists of categories, return a list of categories such that a
+ state appearing in at least one category in each list will appear in at
+ least one category in the returned list.
+ """
+ retval = set()
+ found = set()
+ for x in cats1:
+ for y in cats2:
+ if x == y: continue
+ inter = x.intersect(y)
+ if inter != None:
+ retval.add(inter)
+ found.add(x)
+ found.add(y)
+ if len(found) == 0:
+ return cats1 & cats2
+ return (retval | ((cats1 & cats2) - found))
+
+ def add_hold(self, cat):
+ """
+ Add a hold to a state. Does not check dependencies.
+ """
+ if self.holds.has_key(cat):
+ self.holds[cat] = self.holds[cat] + 1
+ else:
+ self.holds[cat] = 1
+
+ def get_satisfied_states(self, dependents, dependencies):
+ """
+ Given that states in `dependents` depend on states in `dependencies`,
+ return a new Category that contains only the states in `dependents` that
+ could match states in `dependencies`.
+ """
+ retval = []
+ for key, val in self.holds.iteritems():
+ if dependencies.equiv(key) and val > 0:
+ retval.append(dependents.fill(key.args))
+ return set(retval)
+
+ def get_applicable_deps(self, cat):
+ """
+ Find dependencies that might apply to members of `cat`
+ """
+ retval = []
+ for (x, y) in self.deps:
+ if x.equiv(cat):
+ retval.append(y.fill(cat.intersect(x).args))
+ return retval
+
+if __name__ == "__main__":
+ sm = StateMachine()
+ sm.deps.append((Category("mounted", type="nfs"), Category("network_up")))
+ sm.deps.append((Category("mounted", uuid=None, devname=None, label=None), Category("found_disk", uuid=None, devname=None, label=None)))
+ sm.deps.append((Category("mounted", uuid=None, devname=None, label=None), Category("vol_conf", uuid=None, devname=None, label=None)))
+ sm.assert_state(Category("vol_conf", uuid=None, devname=None, label="myroot", type="ext3", mountpoint="/"))
+ sm.assert_state(Category("found_disk", uuid="d3adb3ef", devname="/dev/sda", label="myroot"))
+ sm.assert_state(Category("mounted", uuid=None, type="ext3", devname=None, label=None, mountpoint=None))
+ print sm.holds