1#! /usr/bin/env python3 

2 

3""" Produces a set of graphs of NEW/BYHAND/DEFERRED 

4 

5@contact: Debian FTPMaster <ftpmaster@debian.org> 

6@copyright: 2011 Paul Wise <pabs@debian.org> 

7""" 

8 

9# This program is free software; you can redistribute it and/or modify 

10# it under the terms of the GNU General Public License as published by 

11# the Free Software Foundation; either version 2 of the License, or 

12# (at your option) any later version. 

13 

14# This program is distributed in the hope that it will be useful, 

15# but WITHOUT ANY WARRANTY; without even the implied warranty of 

16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

17# GNU General Public License for more details. 

18 

19# You should have received a copy of the GNU General Public License 

20# along with this program; if not, write to the Free Software 

21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

22 

23import os 

24import sys 

25import colorsys 

26 

27import rrdtool 

28import apt_pkg 

29 

30from daklib import utils 

31 

32Cnf = None 

33default_names = ["byhand", "new", "deferred"] 

34 

35################################################################################ 

36 

37 

38def usage(exit_code=0): 

39 print("""Usage: dak graph 

40Graphs the number of packages in queue directories (usually new and byhand). 

41 

42 -h, --help show this help and exit. 

43 -r, --rrd=key Directory where rrd files to be updated are stored 

44 -x, --extra-rrd=key File containing extra options to rrdtool graphing 

45 -i, --images=key Directory where image graphs to be updated are stored 

46 -n, --names=key A comma separated list of rrd files to be scanned 

47 

48""") 

49 sys.exit(exit_code) 

50 

51################################################################################ 

52 

53 

54def graph(*args): 

55 if args[2] == "deferred": 

56 graph_deferred(*args) 

57 else: 

58 graph_normal(*args) 

59 

60 

61def deferred_colours(): 

62 colours = [0] * 16 

63 for i in range(0, 16): 

64 colours[i] = colorsys.hsv_to_rgb(i / 16.0, 1.0, 0.5 + i / 32.0) 

65 colours[i] = ''.join('%02X' % int(c * 255) for c in colours[i]) 

66 return colours 

67 

68 

69colours = deferred_colours() 

70 

71 

72def graph_deferred(rrd_dir, image_dir, name, extra_args, graph, title, start, year_lines=False): 

73 image_file = os.path.join(image_dir, "%s-%s.png" % (name, graph)) 

74 rrd_file = os.path.join(rrd_dir, "%s.rrd" % name) 

75 rrd_args = [image_file, "--start", start] 

76 rrd_args += (""" 

77--end 

78now 

79--width 

80600 

81--height 

82150 

83--vertical-label 

84changes 

85--title 

86%s changes count for the last %s 

87--lower-limit 

880 

89-E 

90""" % (name.upper(), title)).strip().split("\n") 

91 

92 if year_lines: 

93 rrd_args += ["--x-grid", "MONTH:1:YEAR:1:YEAR:1:31536000:%Y"] 

94 

95 for i in range(0, 16): 

96 rrd_args += (""" 

97DEF:d%i=%s:day%i:AVERAGE 

98AREA:d%i#%s:%i-day changes count:STACK 

99VDEF:ld%i=d%i,LAST 

100VDEF:mind%i=d%i,MINIMUM 

101VDEF:maxd%i=d%i,MAXIMUM 

102VDEF:avgd%i=d%i,AVERAGE 

103GPRINT:ld%i:cur\\: %%.0lf 

104GPRINT:mind%i:min\\: %%.0lf 

105GPRINT:maxd%i:max\\: %%.0lf 

106GPRINT:avgd%i:avg\\: %%.0lf\\j 

107""" % ((i, rrd_file, i, i, colours[i]) + (i,) * 13)).strip().split("\n") 

108 

109 rrd_args += extra_args 

110 try: 

111 ret = rrdtool.graph(*rrd_args) 

112 except rrdtool.error as e: 

113 print(('warning: graph: rrdtool error, skipping %s-%s.png: %s' % (name, graph, e))) 

114 

115 

116def graph_normal(rrd_dir, image_dir, name, extra_args, graph, title, start, year_lines=False): 

117 image_file = os.path.join(image_dir, "%s-%s.png" % (name, graph)) 

118 rrd_file = os.path.join(rrd_dir, "%s.rrd" % name) 

119 rrd_args = [image_file, "--start", start] 

120 rrd_args += (""" 

121--end 

122now 

123--width 

124600 

125--height 

126150 

127--vertical-label 

128packages 

129--title 

130%s package count for the last %s 

131--lower-limit 

1320 

133-E 

134""" % (name.upper(), title)).strip().split("\n") 

135 

136 if year_lines: 

137 rrd_args += ["--x-grid", "MONTH:1:YEAR:1:YEAR:1:31536000:%Y"] 

138 

139 rrd_args += (""" 

140DEF:ds1=%s:ds1:AVERAGE 

141LINE2:ds1#D9382B:changes count 

142VDEF:lds1=ds1,LAST 

143VDEF:minds1=ds1,MINIMUM 

144VDEF:maxds1=ds1,MAXIMUM 

145VDEF:avgds1=ds1,AVERAGE 

146GPRINT:lds1:cur\\: %%.0lf 

147GPRINT:minds1:min\\: %%.0lf 

148GPRINT:maxds1:max\\: %%.0lf 

149GPRINT:avgds1:avg\\: %%.0lf\\j 

150DEF:ds0=%s:ds0:AVERAGE 

151VDEF:lds0=ds0,LAST 

152VDEF:minds0=ds0,MINIMUM 

153VDEF:maxds0=ds0,MAXIMUM 

154VDEF:avgds0=ds0,AVERAGE 

155LINE2:ds0#3069DA:src pkg count 

156GPRINT:lds0:cur\\: %%.0lf 

157GPRINT:minds0:min\\: %%.0lf 

158GPRINT:maxds0:max\\: %%.0lf 

159GPRINT:avgds0:avg\\: %%.0lf\\j 

160""" % (rrd_file, rrd_file)).strip().split("\n") 

161 

162 rrd_args += extra_args 

163 try: 

164 ret = rrdtool.graph(*rrd_args) 

165 except rrdtool.error as e: 

166 print(('warning: graph: rrdtool error, skipping %s-%s.png: %s' % (name, graph, e))) 

167 

168################################################################################ 

169 

170 

171def main(): 

172 global Cnf 

173 

174 Cnf = utils.get_conf() 

175 Arguments = [('h', "help", "Graph::Options::Help"), 

176 ('x', "extra-rrd", "Graph::Options::Extra-Rrd", "HasArg"), 

177 ('r', "rrd", "Graph::Options::Rrd", "HasArg"), 

178 ('i', "images", "Graph::Options::Images", "HasArg"), 

179 ('n', "names", "Graph::Options::Names", "HasArg")] 

180 for i in ["help"]: 

181 key = "Graph::Options::%s" % i 

182 if key not in Cnf: 182 ↛ 180line 182 didn't jump to line 180, because the condition on line 182 was never false

183 Cnf[key] = "" 

184 

185 apt_pkg.parse_commandline(Cnf, Arguments, sys.argv) 

186 

187 Options = Cnf.subtree("Graph::Options") 

188 if Options["Help"]: 188 ↛ 191line 188 didn't jump to line 191, because the condition on line 188 was never false

189 usage() 

190 

191 names = [] 

192 

193 if "Graph::Options::Names" in Cnf: 

194 for i in Cnf["Graph::Options::Names"].split(","): 

195 names.append(i) 

196 elif "Graph::Names" in Cnf: 

197 names = Cnf.value_list("Graph::Names") 

198 else: 

199 names = default_names 

200 

201 extra_rrdtool_args = [] 

202 

203 if "Graph::Options::Extra-Rrd" in Cnf: 

204 for i in Cnf["Graph::Options::Extra-Rrd"].split(","): 

205 with open(i) as f: 

206 extra_rrdtool_args.extend(f.read().strip().split("\n")) 

207 elif "Graph::Extra-Rrd" in Cnf: 

208 for i in Cnf.value_list("Graph::Extra-Rrd"): 

209 with open(i) as f: 

210 extra_rrdtool_args.extend(f.read().strip().split("\n")) 

211 

212 if "Graph::Options::Rrd" in Cnf: 

213 rrd_dir = Cnf["Graph::Options::Rrd"] 

214 elif "Dir::Rrd" in Cnf: 

215 rrd_dir = Cnf["Dir::Rrd"] 

216 else: 

217 print("No directory to read RRD files from\n", file=sys.stderr) 

218 sys.exit(1) 

219 

220 if "Graph::Options::Images" in Cnf: 

221 image_dir = Cnf["Graph::Options::Images"] 

222 else: 

223 print("No directory to write graph images to\n", file=sys.stderr) 

224 sys.exit(1) 

225 

226 for name in names: 

227 stdargs = [rrd_dir, image_dir, name, extra_rrdtool_args] 

228 graph(*(stdargs + ['day', 'day', 'now-1d'])) 

229 graph(*(stdargs + ['week', 'week', 'now-1w'])) 

230 graph(*(stdargs + ['month', 'month', 'now-1m'])) 

231 graph(*(stdargs + ['year', 'year', 'now-1y'])) 

232 graph(*(stdargs + ['5years', '5 years', 'now-5y', True])) 

233 graph(*(stdargs + ['10years', '10 years', 'now-10y', True])) 

234 

235################################################################################ 

236 

237 

238if __name__ == '__main__': 

239 main()