Differences between revisions 4 and 5
Revision 4 as of 2006-02-13 18:40:05
Size: 5751
Editor: JoeyHess
Comment:
Revision 5 as of 2006-02-14 22:01:37
Size: 5756
Editor: ?GeertStappers
Comment: valid html
Deletions are marked like this. Additions are marked like this.
Line 120: Line 120:
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3c.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\";> <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3c.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
Line 146: Line 146:
        print "</table></td><td rowspan='2'><img src='%s'></td></tr></table>" \         print "</table></td><td rowspan='2'><img src='%s'></td></img></tr></table>" \

The Partman Partition Recipe Calculator was original posted to the [http://lists.debian.org/debian-boot/2005/05/msg00381.html debian-boot mailinglist]

   1 #!/usr/bin/env python
   2 # Copyright 2005 W. Borgert, distribute under GNU General Public License v2
   3 # Create HTML visualisation of hard-disk partitioning recipe
   4 
   5 import os
   6 import sys
   7 import gdchart
   8 import pyparsing as pp
   9 
  10 
  11 class Partition:
  12     def __init__(self, min, priority, max, max_relative, use):
  13         self.min_orig = min
  14         self.max_orig = max
  15         self.min = min
  16         self.priority = priority
  17         self.max = max
  18         self.max_relative = max_relative
  19         self.use = use
  20         self.factor = priority - min
  21 
  22     def reset(self):
  23         self.min = self.min_orig
  24         self.max = self.max_orig
  25 
  26 
  27 class Recipe:
  28     """Pseudo parser for recipe files."""
  29     def __init__(self):
  30         self.bnf = self.createBNF()
  31         self.partitions = []
  32         self.init_values()
  33 
  34     def init_values(self):
  35         self.min = 0
  36         self.priority = 0
  37         self.max = 0
  38         self.max_relative = False
  39         self.use = ""
  40 
  41     def createBNF(self):
  42         Identifier = pp.Word(pp.alphas, pp.alphanums + "_-/")
  43         FileContents = pp.Word(pp.alphanums + "-/")
  44         Specifier = (pp.Optional(pp.Literal("$")) + Identifier \
  45                      + pp.Literal("{") + pp.ZeroOrMore(FileContents) \
  46                      + pp.Literal("}"))
  47         Specifier.setParseAction(self.set_use)
  48         Priority = pp.Word(pp.nums)
  49         Priority.setParseAction(self.set_priority)
  50         MaximalSize = pp.Word(pp.nums) + pp.Optional(pp.Literal("%"))
  51         MaximalSize.setParseAction(self.set_max)
  52         MinimalSize = pp.Word(pp.nums)
  53         MinimalSize.setParseAction(self.set_min)
  54         Limits = MinimalSize + Priority + MaximalSize + Identifier
  55         Partition = (Limits + pp.OneOrMore(Specifier) + pp.Literal("."))
  56         Partition.setParseAction(self.finish_partition)
  57         Header = Identifier + (pp.Literal("::") ^ pp.Literal(":"))
  58         bnf = (Header + pp.OneOrMore(Partition) + pp.StringEnd())
  59         bnf.ignore(pp.Literal("#") + pp.restOfLine)
  60         return bnf
  61 
  62     def set_min(self, s, loc, toks):
  63         self.min = int(toks[0])
  64 
  65     def set_priority(self, s, loc, toks):
  66         self.priority = int(toks[0])
  67 
  68     def set_max(self, s, loc, toks):
  69         self.max = int(toks[0])
  70         if len(toks) > 1:
  71             self.max_relative = True
  72 
  73     def set_use(self, s, loc, toks):
  74         if len(toks) > 3 and toks[0] == "mountpoint":
  75             self.use = toks[2]
  76         elif len(toks) > 3 and toks[0] == "method" and toks[2] == "swap":
  77             self.use = "swap"
  78 
  79     def finish_partition(self, s, loc, toks):
  80         self.partitions.append(Partition(
  81             self.min, self.priority, self.max, self.max_relative, self.use))
  82         self.init_values()
  83 
  84 
  85 def calculate(partitions, free_space, memory):
  86     for p in recipe.partitions:
  87         p.reset()
  88     ready = False
  89     while not ready:
  90         minsum = factsum = 0
  91         for p in partitions:
  92             if p.max_relative:
  93                 p.max = p.max * memory / 100.
  94             minsum += p.min
  95             factsum += p.factor
  96         ready = True
  97         for p in partitions:
  98             x = p.min + (free_space - minsum) * p.factor / factsum
  99             if x > p.max:
 100                 x = p.max
 101             if x != p.min:
 102                 ready = False
 103                 p.min = x
 104 
 105 
 106 if __name__ == '__main__':
 107     if len(sys.argv) < 3:
 108         print >>sys.stderr, \
 109               """Usage: %s <recipe file> {<free space>:<memory>}+
 110 e.g. %s server.rec 160000:1024 200000:2048""" % (sys.argv[0], sys.argv[0])
 111         sys.exit(-1)
 112     recipe = Recipe()
 113     recipe.bnf.parseFile(sys.argv[1])
 114     print """<?xml version='1.0' encoding='utf-8'?>
 115 <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3c.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
 116 <html><head><title>Partitioning</title></head><body><h1>Partitioning</h1>"""
 117     pie = gdchart.Pie3D()
 118     pie.bg_color = "white"
 119     pie.color = map(
 120         lambda c: gdchart.RGB(c[0], c[1], c[2]),
 121         [(0xff, 0xff, 0x00), (0xff, 0xa5, 0x00), (0xff, 0x00, 0x00),
 122          (0xff, 0x00, 0xff), (0x80, 0x00, 0x80), (0x80, 0x00, 0x00),
 123          (0x00, 0xff, 0xff), (0x00, 0xff, 0x00), (0x00, 0x80, 0x80),
 124          (0x00, 0x80, 0x00), (0x00, 0x00, 0xff), (0x00, 0x00, 0x80)])
 125     for spec in sys.argv[2:]:
 126         free_space, memory = map(lambda x: int(x), spec.split(":"))
 127         filename = "hd-%d-%d.png" % (free_space, memory)
 128         if os.path.exists(filename):
 129             print >>sys.stderr, \
 130                   "file %s already exists - not overwriting" % filename
 131             continue
 132         calculate(recipe.partitions, free_space, memory)
 133         print """<table border='0'><tr valign='center'><td>
 134 <table border='0'>
 135 <tr><th align='left'>Hard Disk</th><td align='right'>%d</td></tr>
 136 <tr><th align='left'>Memory</th><td align='right'>%d</td></tr>""" \
 137               % (free_space, memory)
 138         for p in recipe.partitions:
 139             print "<tr><th align='left'>%s</th><td align='right'>%d</td></tr>" \
 140                   % (p.use, p.min)
 141         print "</table></td><td rowspan='2'><img src='%s'></td></img></tr></table>" \
 142               % filename
 143         apply(pie.setData, [p.min for p in recipe.partitions])
 144         pie.setLabels([("%d %s" % (p.min/1024., p.use))[:11]
 145                        for p in recipe.partitions])
 146         pie.draw(filename)
 147     print "</body></html>"