web: add 'Repair' button to checker results when they indicate unhealthyness. Also add the object's uri to the CheckerResults instance.
This commit is contained in:
parent
6a7d5b893b
commit
b1db6d9ff2
|
@ -7,7 +7,9 @@ from allmydata.util import base32
|
||||||
class CheckerResults:
|
class CheckerResults:
|
||||||
implements(ICheckerResults)
|
implements(ICheckerResults)
|
||||||
|
|
||||||
def __init__(self, storage_index):
|
def __init__(self, uri, storage_index):
|
||||||
|
assert isinstance(uri, str)
|
||||||
|
self.uri = uri
|
||||||
self.storage_index = storage_index
|
self.storage_index = storage_index
|
||||||
self.problems = []
|
self.problems = []
|
||||||
self.data = {"count-corrupt-shares": 0,
|
self.data = {"count-corrupt-shares": 0,
|
||||||
|
@ -38,6 +40,8 @@ class CheckerResults:
|
||||||
return self.storage_index
|
return self.storage_index
|
||||||
def get_storage_index_string(self):
|
def get_storage_index_string(self):
|
||||||
return base32.b2a(self.storage_index)
|
return base32.b2a(self.storage_index)
|
||||||
|
def get_uri(self):
|
||||||
|
return self.uri
|
||||||
|
|
||||||
def is_healthy(self):
|
def is_healthy(self):
|
||||||
return self.healthy
|
return self.healthy
|
||||||
|
|
|
@ -17,11 +17,12 @@ class SimpleCHKFileChecker:
|
||||||
"""Return a list of (needed, total, found, sharemap), where sharemap maps
|
"""Return a list of (needed, total, found, sharemap), where sharemap maps
|
||||||
share number to a list of (binary) nodeids of the shareholders."""
|
share number to a list of (binary) nodeids of the shareholders."""
|
||||||
|
|
||||||
def __init__(self, client, storage_index, needed_shares, total_shares):
|
def __init__(self, client, uri, storage_index, needed_shares, total_shares):
|
||||||
self.peer_getter = client.get_permuted_peers
|
self.peer_getter = client.get_permuted_peers
|
||||||
self.needed_shares = needed_shares
|
self.needed_shares = needed_shares
|
||||||
self.total_shares = total_shares
|
self.total_shares = total_shares
|
||||||
self.found_shares = set()
|
self.found_shares = set()
|
||||||
|
self.uri = uri
|
||||||
self.storage_index = storage_index
|
self.storage_index = storage_index
|
||||||
self.sharemap = {}
|
self.sharemap = {}
|
||||||
self.responded = set()
|
self.responded = set()
|
||||||
|
@ -67,7 +68,7 @@ class SimpleCHKFileChecker:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _done(self, res):
|
def _done(self, res):
|
||||||
r = CheckerResults(self.storage_index)
|
r = CheckerResults(self.uri, self.storage_index)
|
||||||
report = []
|
report = []
|
||||||
healthy = bool(len(self.found_shares) >= self.total_shares)
|
healthy = bool(len(self.found_shares) >= self.total_shares)
|
||||||
r.set_healthy(healthy)
|
r.set_healthy(healthy)
|
||||||
|
@ -151,9 +152,10 @@ class SimpleCHKFileVerifier(download.FileDownloader):
|
||||||
# remaining shareholders, and it cannot verify the plaintext.
|
# remaining shareholders, and it cannot verify the plaintext.
|
||||||
check_plaintext_hash = False
|
check_plaintext_hash = False
|
||||||
|
|
||||||
def __init__(self, client, storage_index, k, N, size, ueb_hash):
|
def __init__(self, client, uri, storage_index, k, N, size, ueb_hash):
|
||||||
self._client = client
|
self._client = client
|
||||||
|
|
||||||
|
self._uri = uri
|
||||||
self._storage_index = storage_index
|
self._storage_index = storage_index
|
||||||
self._uri_extension_hash = ueb_hash
|
self._uri_extension_hash = ueb_hash
|
||||||
self._total_shares = N
|
self._total_shares = N
|
||||||
|
@ -163,7 +165,7 @@ class SimpleCHKFileVerifier(download.FileDownloader):
|
||||||
self._si_s = storage.si_b2a(self._storage_index)
|
self._si_s = storage.si_b2a(self._storage_index)
|
||||||
self.init_logging()
|
self.init_logging()
|
||||||
|
|
||||||
self._check_results = r = CheckerResults(self._storage_index)
|
self._check_results = r = CheckerResults(self._uri, self._storage_index)
|
||||||
r.set_data({"count-shares-needed": k,
|
r.set_data({"count-shares-needed": k,
|
||||||
"count-shares-expected": N,
|
"count-shares-expected": N,
|
||||||
})
|
})
|
||||||
|
|
|
@ -196,9 +196,12 @@ class FileNode(_ImmutableFileNodeBase):
|
||||||
ueb_hash = self.u.uri_extension_hash
|
ueb_hash = self.u.uri_extension_hash
|
||||||
if verify:
|
if verify:
|
||||||
v = self.verifier_class(self._client,
|
v = self.verifier_class(self._client,
|
||||||
storage_index, k, N, size, ueb_hash)
|
self.get_uri(), storage_index,
|
||||||
|
k, N, size, ueb_hash)
|
||||||
else:
|
else:
|
||||||
v = self.checker_class(self._client, storage_index, k, N)
|
v = self.checker_class(self._client,
|
||||||
|
self.get_uri(), storage_index,
|
||||||
|
k, N)
|
||||||
return v.start()
|
return v.start()
|
||||||
|
|
||||||
def check_and_repair(self, monitor, verify=False):
|
def check_and_repair(self, monitor, verify=False):
|
||||||
|
|
|
@ -1607,6 +1607,8 @@ class ICheckerResults(Interface):
|
||||||
"""Return a string with the (binary) storage index."""
|
"""Return a string with the (binary) storage index."""
|
||||||
def get_storage_index_string():
|
def get_storage_index_string():
|
||||||
"""Return a string with the (printable) abbreviated storage index."""
|
"""Return a string with the (printable) abbreviated storage index."""
|
||||||
|
def get_uri():
|
||||||
|
"""Return the (string) URI of the object that was checked."""
|
||||||
|
|
||||||
def is_healthy():
|
def is_healthy():
|
||||||
"""Return a boolean, True if the file/dir is fully healthy, False if
|
"""Return a boolean, True if the file/dir is fully healthy, False if
|
||||||
|
|
|
@ -16,7 +16,7 @@ class MutableChecker:
|
||||||
self._monitor = monitor
|
self._monitor = monitor
|
||||||
self.bad_shares = [] # list of (nodeid,shnum,failure)
|
self.bad_shares = [] # list of (nodeid,shnum,failure)
|
||||||
self._storage_index = self._node.get_storage_index()
|
self._storage_index = self._node.get_storage_index()
|
||||||
self.results = CheckerResults(self._storage_index)
|
self.results = CheckerResults(node.get_uri(), self._storage_index)
|
||||||
self.need_repair = False
|
self.need_repair = False
|
||||||
self.responded = set() # set of (binary) nodeids
|
self.responded = set() # set of (binary) nodeids
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ class MutableCheckAndRepairer(MutableChecker):
|
||||||
d = self._node.repair(self.results)
|
d = self._node.repair(self.results)
|
||||||
def _repair_finished(repair_results):
|
def _repair_finished(repair_results):
|
||||||
self.cr_results.repair_successful = True
|
self.cr_results.repair_successful = True
|
||||||
r = CheckerResults(self._storage_index)
|
r = CheckerResults(self._node.get_uri(), self._storage_index)
|
||||||
self.cr_results.post_repair_results = r
|
self.cr_results.post_repair_results = r
|
||||||
self._fill_checker_results(repair_results.servermap, r)
|
self._fill_checker_results(repair_results.servermap, r)
|
||||||
self.cr_results.repair_results = repair_results # TODO?
|
self.cr_results.repair_results = repair_results # TODO?
|
||||||
|
|
|
@ -51,7 +51,7 @@ class FakeCHKFileNode:
|
||||||
return self.storage_index
|
return self.storage_index
|
||||||
|
|
||||||
def check(self, monitor, verify=False):
|
def check(self, monitor, verify=False):
|
||||||
r = CheckerResults(self.storage_index)
|
r = CheckerResults(self.my_uri, self.storage_index)
|
||||||
is_bad = self.bad_shares.get(self.storage_index, None)
|
is_bad = self.bad_shares.get(self.storage_index, None)
|
||||||
data = {}
|
data = {}
|
||||||
data["count-shares-needed"] = 3
|
data["count-shares-needed"] = 3
|
||||||
|
@ -183,7 +183,7 @@ class FakeMutableFileNode:
|
||||||
return self.storage_index
|
return self.storage_index
|
||||||
|
|
||||||
def check(self, monitor, verify=False):
|
def check(self, monitor, verify=False):
|
||||||
r = CheckerResults(self.storage_index)
|
r = CheckerResults(self.my_uri.to_string(), self.storage_index)
|
||||||
is_bad = self.bad_shares.get(self.storage_index, None)
|
is_bad = self.bad_shares.get(self.storage_index, None)
|
||||||
data = {}
|
data = {}
|
||||||
data["count-shares-needed"] = 3
|
data["count-shares-needed"] = 3
|
||||||
|
|
|
@ -37,7 +37,7 @@ class Marker:
|
||||||
return self.verifieruri
|
return self.verifieruri
|
||||||
|
|
||||||
def check(self, monitor, verify=False):
|
def check(self, monitor, verify=False):
|
||||||
r = CheckerResults(None)
|
r = CheckerResults("", None)
|
||||||
r.set_healthy(True)
|
r.set_healthy(True)
|
||||||
return defer.succeed(r)
|
return defer.succeed(r)
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
<span n:render="rebalance" />
|
<span n:render="rebalance" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div n:render="repair" />
|
||||||
|
|
||||||
<div n:render="results" />
|
<div n:render="results" />
|
||||||
|
|
||||||
<div n:render="return" />
|
<div n:render="return" />
|
||||||
|
|
|
@ -183,6 +183,18 @@ class CheckerResults(CheckerBase, rend.Page, ResultsBase):
|
||||||
return ctx.tag["Healthy!"]
|
return ctx.tag["Healthy!"]
|
||||||
return ctx.tag["Not Healthy!: ", self._html(self.r.get_summary())]
|
return ctx.tag["Not Healthy!: ", self._html(self.r.get_summary())]
|
||||||
|
|
||||||
|
def render_repair(self, ctx, data):
|
||||||
|
if self.r.is_healthy():
|
||||||
|
return ""
|
||||||
|
repair = T.form(action=".", method="post",
|
||||||
|
enctype="multipart/form-data")[
|
||||||
|
T.fieldset[
|
||||||
|
T.input(type="hidden", name="t", value="check"),
|
||||||
|
T.input(type="hidden", name="repair", value="true"),
|
||||||
|
T.input(type="submit", value="Repair"),
|
||||||
|
]]
|
||||||
|
return ctx.tag[repair]
|
||||||
|
|
||||||
def render_rebalance(self, ctx, data):
|
def render_rebalance(self, ctx, data):
|
||||||
if self.r.needs_rebalancing():
|
if self.r.needs_rebalancing():
|
||||||
return ctx.tag["(needs rebalancing)"]
|
return ctx.tag["(needs rebalancing)"]
|
||||||
|
|
Loading…
Reference in New Issue