3 from twisted.trial import unittest
4 from allmydata import check_results, uri
5 from allmydata.web import check_results as web_check_results
6 from allmydata.storage_client import StorageFarmBroker, NativeStorageClient
7 from common_web import WebRenderingMixin
10 def get_nickname_for_serverid(self, serverid):
11 return self.storage_broker.get_nickname_for_serverid(serverid)
12 def get_storage_broker(self):
13 return self.storage_broker
15 class WebResultsRendering(unittest.TestCase, WebRenderingMixin):
17 def create_fake_client(self):
18 sb = StorageFarmBroker()
19 for (peerid, nickname) in [("\x00"*20, "peer-0"),
20 ("\xff"*20, "peer-f"),
21 ("\x11"*20, "peer-11")] :
22 n = NativeStorageClient(peerid, None, nickname)
23 sb.add_server(peerid, n)
28 def render_json(self, page):
29 d = self.render1(page, args={"output": ["json"]})
32 def test_literal(self):
33 c = self.create_fake_client()
34 lcr = web_check_results.LiteralCheckResults(c)
38 s = self.remove_tags(html)
39 self.failUnlessIn("Literal files are always healthy", s)
41 d.addCallback(lambda ignored:
42 self.render1(lcr, args={"return_to": ["FOOURL"]}))
43 def _check_return_to(html):
44 s = self.remove_tags(html)
45 self.failUnlessIn("Literal files are always healthy", s)
46 self.failUnlessIn('<a href="FOOURL">Return to file.</a>',
48 d.addCallback(_check_return_to)
49 d.addCallback(lambda ignored: self.render_json(lcr))
50 def _check_json(json):
51 j = simplejson.loads(json)
52 self.failUnlessEqual(j["storage-index"], "")
53 self.failUnlessEqual(j["results"]["healthy"], True)
54 d.addCallback(_check_json)
58 c = self.create_fake_client()
59 serverid_1 = "\x00"*20
60 serverid_f = "\xff"*20
61 u = uri.CHKFileURI("\x00"*16, "\x00"*32, 3, 10, 1234)
62 cr = check_results.CheckResults(u, u.storage_index)
64 cr.set_needs_rebalancing(False)
65 cr.set_summary("groovy")
66 data = { "count-shares-needed": 3,
67 "count-shares-expected": 9,
68 "count-shares-good": 10,
69 "count-good-share-hosts": 11,
70 "list-corrupt-shares": [],
71 "count-wrong-shares": 0,
72 "sharemap": {"shareid1": [serverid_1, serverid_f]},
73 "count-recoverable-versions": 1,
74 "count-unrecoverable-versions": 0,
75 "servers-responding": [],
79 w = web_check_results.CheckResults(c, cr)
80 html = self.render2(w)
81 s = self.remove_tags(html)
82 self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated
83 self.failUnlessIn("Healthy : groovy", s)
84 self.failUnlessIn("Share Counts: need 3-of-9, have 10", s)
85 self.failUnlessIn("Hosts with good shares: 11", s)
86 self.failUnlessIn("Corrupt shares: none", s)
87 self.failUnlessIn("Wrong Shares: 0", s)
88 self.failUnlessIn("Recoverable Versions: 1", s)
89 self.failUnlessIn("Unrecoverable Versions: 0", s)
92 cr.set_recoverable(True)
93 cr.set_summary("ungroovy")
94 html = self.render2(w)
95 s = self.remove_tags(html)
96 self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated
97 self.failUnlessIn("Not Healthy! : ungroovy", s)
100 cr.set_recoverable(False)
101 cr.set_summary("rather dead")
102 data["list-corrupt-shares"] = [(serverid_1, u.storage_index, 2)]
104 html = self.render2(w)
105 s = self.remove_tags(html)
106 self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated
107 self.failUnlessIn("Not Recoverable! : rather dead", s)
108 self.failUnlessIn("Corrupt shares: Share ID Nickname Node ID sh#2 peer-0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", s)
110 html = self.render2(w)
111 s = self.remove_tags(html)
112 self.failUnlessIn("File Check Results for SI=2k6avp", s) # abbreviated
113 self.failUnlessIn("Not Recoverable! : rather dead", s)
115 html = self.render2(w, args={"return_to": ["FOOURL"]})
116 self.failUnlessIn('<a href="FOOURL">Return to file/directory.</a>',
119 d = self.render_json(w)
120 def _check_json(jdata):
121 j = simplejson.loads(jdata)
122 self.failUnlessEqual(j["summary"], "rather dead")
123 self.failUnlessEqual(j["storage-index"],
124 "2k6avpjga3dho3zsjo6nnkt7n4")
125 expected = {'needs-rebalancing': False,
126 'count-shares-expected': 9,
128 'count-unrecoverable-versions': 0,
129 'count-shares-needed': 3,
130 'sharemap': {"shareid1":
131 ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
132 "77777777777777777777777777777777"]},
133 'count-recoverable-versions': 1,
134 'list-corrupt-shares':
135 [["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
136 "2k6avpjga3dho3zsjo6nnkt7n4", 2]],
137 'count-good-share-hosts': 11,
138 'count-wrong-shares': 0,
139 'count-shares-good': 10,
140 'count-corrupt-shares': 0,
141 'servers-responding': [],
142 'recoverable': False,
144 self.failUnlessEqual(j["results"], expected)
145 d.addCallback(_check_json)
146 d.addCallback(lambda ignored: self.render1(w))
148 s = self.remove_tags(html)
149 self.failUnlessIn("File Check Results for SI=2k6avp", s)
150 self.failUnlessIn("Not Recoverable! : rather dead", s)
151 d.addCallback(_check)
155 def test_check_and_repair(self):
156 c = self.create_fake_client()
157 serverid_1 = "\x00"*20
158 serverid_f = "\xff"*20
159 u = uri.CHKFileURI("\x00"*16, "\x00"*32, 3, 10, 1234)
161 pre_cr = check_results.CheckResults(u, u.storage_index)
162 pre_cr.set_healthy(False)
163 pre_cr.set_recoverable(True)
164 pre_cr.set_needs_rebalancing(False)
165 pre_cr.set_summary("illing")
166 data = { "count-shares-needed": 3,
167 "count-shares-expected": 10,
168 "count-shares-good": 6,
169 "count-good-share-hosts": 7,
170 "list-corrupt-shares": [],
171 "count-wrong-shares": 0,
172 "sharemap": {"shareid1": [serverid_1, serverid_f]},
173 "count-recoverable-versions": 1,
174 "count-unrecoverable-versions": 0,
175 "servers-responding": [],
177 pre_cr.set_data(data)
179 post_cr = check_results.CheckResults(u, u.storage_index)
180 post_cr.set_healthy(True)
181 post_cr.set_recoverable(True)
182 post_cr.set_needs_rebalancing(False)
183 post_cr.set_summary("groovy")
184 data = { "count-shares-needed": 3,
185 "count-shares-expected": 10,
186 "count-shares-good": 10,
187 "count-good-share-hosts": 11,
188 "list-corrupt-shares": [],
189 "count-wrong-shares": 0,
190 "sharemap": {"shareid1": [serverid_1, serverid_f]},
191 "count-recoverable-versions": 1,
192 "count-unrecoverable-versions": 0,
193 "servers-responding": [],
195 post_cr.set_data(data)
197 crr = check_results.CheckAndRepairResults(u.storage_index)
198 crr.pre_repair_results = pre_cr
199 crr.post_repair_results = post_cr
200 crr.repair_attempted = False
202 w = web_check_results.CheckAndRepairResults(c, crr)
203 html = self.render2(w)
204 s = self.remove_tags(html)
206 self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s)
207 self.failUnlessIn("Healthy : groovy", s)
208 self.failUnlessIn("No repair necessary", s)
209 self.failUnlessIn("Post-Repair Checker Results:", s)
210 self.failUnlessIn("Share Counts: need 3-of-10, have 10", s)
212 crr.repair_attempted = True
213 crr.repair_successful = True
214 html = self.render2(w)
215 s = self.remove_tags(html)
217 self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s)
218 self.failUnlessIn("Healthy : groovy", s)
219 self.failUnlessIn("Repair successful", s)
220 self.failUnlessIn("Post-Repair Checker Results:", s)
222 crr.repair_attempted = True
223 crr.repair_successful = False
224 post_cr.set_healthy(False)
225 post_cr.set_summary("better")
226 html = self.render2(w)
227 s = self.remove_tags(html)
229 self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s)
230 self.failUnlessIn("Not Healthy! : better", s)
231 self.failUnlessIn("Repair unsuccessful", s)
232 self.failUnlessIn("Post-Repair Checker Results:", s)
234 crr.repair_attempted = True
235 crr.repair_successful = False
236 post_cr.set_healthy(False)
237 post_cr.set_recoverable(False)
238 post_cr.set_summary("worse")
239 html = self.render2(w)
240 s = self.remove_tags(html)
242 self.failUnlessIn("File Check-And-Repair Results for SI=2k6avp", s)
243 self.failUnlessIn("Not Recoverable! : worse", s)
244 self.failUnlessIn("Repair unsuccessful", s)
245 self.failUnlessIn("Post-Repair Checker Results:", s)
247 d = self.render_json(w)
249 j = simplejson.loads(data)
250 self.failUnlessEqual(j["repair-attempted"], True)
251 self.failUnlessEqual(j["storage-index"],
252 "2k6avpjga3dho3zsjo6nnkt7n4")
253 self.failUnlessEqual(j["pre-repair-results"]["summary"], "illing")
254 self.failUnlessEqual(j["post-repair-results"]["summary"], "worse")
255 d.addCallback(_got_json)
257 w2 = web_check_results.CheckAndRepairResults(c, None)
258 d.addCallback(lambda ignored: self.render_json(w2))
259 def _got_lit_results(data):
260 j = simplejson.loads(data)
261 self.failUnlessEqual(j["repair-attempted"], False)
262 self.failUnlessEqual(j["storage-index"], "")
263 d.addCallback(_got_lit_results)