summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCasey Dahlin <cdahlin@redhat.com>2008-12-21 20:14:52 -0500
committerCasey Dahlin <cdahlin@redhat.com>2008-12-21 20:14:52 -0500
commit24781fbc3ad4640b360e92561948f412fbb7ef3e (patch)
treefb6964cc9843d41aa79e96502c967135402edbad
parent8962d343063795e1d9eb6b2c5d53e90c405c59c5 (diff)
downloadupstate-24781fbc3ad4640b360e92561948f412fbb7ef3e.tar.gz
upstate-24781fbc3ad4640b360e92561948f412fbb7ef3e.tar.xz
upstate-24781fbc3ad4640b360e92561948f412fbb7ef3e.zip
Beginnings of python rewrite
-rw-r--r--.gitignore1
-rw-r--r--legacy/example.rb (renamed from example.rb)0
-rw-r--r--legacy/state.rb (renamed from state.rb)0
-rw-r--r--legacy/test.rb (renamed from test.rb)0
-rw-r--r--legacy/test2.rb (renamed from test2.rb)0
-rw-r--r--state.py154
6 files changed, 155 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index d926099..64ae595 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
.*.swp
+*.pyc
coverage/
diff --git a/example.rb b/legacy/example.rb
index 182ae1d..182ae1d 100644
--- a/example.rb
+++ b/legacy/example.rb
diff --git a/state.rb b/legacy/state.rb
index 02c1bf3..02c1bf3 100644
--- a/state.rb
+++ b/legacy/state.rb
diff --git a/test.rb b/legacy/test.rb
index 87cb5bf..87cb5bf 100644
--- a/test.rb
+++ b/legacy/test.rb
diff --git a/test2.rb b/legacy/test2.rb
index 0a43d58..0a43d58 100644
--- a/test2.rb
+++ b/legacy/test2.rb
diff --git a/state.py b/state.py
new file mode 100644
index 0000000..594b32a
--- /dev/null
+++ b/state.py
@@ -0,0 +1,154 @@
+#
+class Category:
+ def __init__(self, name, **args):
+ self.args = args
+ self.name = name
+
+ def equiv(self, other):
+ if self.name != other.name: return False
+ for key, value in self.args.iteritems():
+ if not other.args.has_key(key): return False
+ if value == None: continue
+ if other.args[key] == None: continue
+ if not other.args[key] == value: return False
+ return True
+
+ def intersect(self, other):
+ if self.name != other.name: return None
+ args = {}
+ for key in list(set(self.args.keys() + other.args.keys())):
+ if not self.args.has_key(key):
+ args[key] = other.args[key]
+ elif not other.args.has_key(key):
+ args[key] = self.args[key]
+ elif self.args[key] == None:
+ args[key] = other.args[key]
+ elif other.args[key] == None:
+ args[key] = self.args[key]
+ elif self.args[key] != other.args[key]:
+ return None
+ else: # self.args[key] == other.args[key]
+ args[key] = self.args[key]
+ return Category(self.name, **args)
+
+ def __str__(self):
+ string = self.name + "("
+ had = False
+ for key, val in self.args.iteritems():
+ if had:
+ string += ", "
+ had = True
+ if val == None:
+ string += "%%%s" % key
+ else:
+ string += "%s: %s" % (key, val)
+ return string + ")"
+
+ def __repr__(self):
+ return self.__str__()
+
+ def __hash__(self):
+ return hash((self.argstup(), self.name))
+
+ def __eq__(self, other):
+ return self.name == other.name and self.argstup() == other.argstup()
+
+ def argstup(self):
+ retval = []
+ keys = self.args.keys()
+ keys.sort()
+ for key in keys:
+ retval.append((key, self.args[key]))
+ return tuple(retval)
+
+ def filter(self, other):
+ if not other.name == self.name:
+ raise TypeError, "States must be the same class"
+ args = {}
+ for key, value in other.args.iteritems():
+ if value != None or not self.args.has_key(key):
+ args[key] = value
+ else:
+ args[key] = self.args[key]
+ return Category(self.name, **args)
+
+ def fill(self, info):
+ args = {}
+ for key, value in self.args.iteritems():
+ if value != None or not info.has_key(key):
+ args[key] = value
+ else:
+ args[key] = info[key]
+ return Category(self.name, **args)
+
+ def is_finite(self):
+ return not None in self.args.values()
+
+class StateMachine:
+ def __init__(self):
+ self.holds = {}
+ self.deps = []
+
+ def assert_state(self, cat):
+ 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):
+ 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):
+ 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):
+ 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):
+ retval = []
+ for (x, y) in self.deps:
+ if x.equiv(cat):
+ retval.append(y.fill(cat.filter(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