source: trunk/src/allmydata/scripts/slow_operation.py

Last change on this file was 53084f7, checked in by Alexandre Detiste <alexandre.detiste@…>, at 2024-02-27T23:49:07Z

remove more Python2 compatibility

  • Property mode set to 100644
File size: 3.0 KB
Line 
1"""
2Ported to Python 3.
3"""
4
5from six import ensure_str
6
7import os, time
8from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path, \
9                                     UnknownAliasError
10from allmydata.scripts.common_http import do_http, format_http_error
11from allmydata.util import base32
12from allmydata.util.encodingutil import quote_output, is_printable_ascii
13from urllib.parse import quote as url_quote
14import json
15
16class SlowOperationRunner(object):
17
18    def run(self, options):
19        stderr = options.stderr
20        self.options = options
21        self.ophandle = ophandle = ensure_str(base32.b2a(os.urandom(16)))
22        nodeurl = options['node-url']
23        if not nodeurl.endswith("/"):
24            nodeurl += "/"
25        self.nodeurl = nodeurl
26        where = options.where
27        try:
28            rootcap, path = get_alias(options.aliases, where, DEFAULT_ALIAS)
29        except UnknownAliasError as e:
30            e.display(stderr)
31            return 1
32        path = str(path, "utf-8")
33        if path == '/':
34            path = ''
35        url = nodeurl + "uri/%s" % url_quote(rootcap)
36        if path:
37            url += "/" + escape_path(path)
38        # todo: should it end with a slash?
39        url = self.make_url(url, ophandle)
40        resp = do_http("POST", url)
41        if resp.status not in (200, 302):
42            print(format_http_error("ERROR", resp), file=stderr)
43            return 1
44        # now we poll for results. We nominally poll at t=1, 5, 10, 30, 60,
45        # 90, k*120 seconds, but if the poll takes non-zero time, that will
46        # be slightly longer. I'm not worried about trying to make up for
47        # that time.
48
49        return self.wait_for_results()
50
51    def poll_times(self):
52        for i in (1,5,10,30,60,90):
53            yield i
54        i = 120
55        while True:
56            yield i
57            i += 120
58
59    def wait_for_results(self):
60        last = 0
61        for next_item in self.poll_times():
62            delay = next_item - last
63            time.sleep(delay)
64            last = next_item
65            if self.poll():
66                return 0
67
68    def poll(self):
69        url = self.nodeurl + "operations/" + self.ophandle
70        url += "?t=status&output=JSON&release-after-complete=true"
71        stdout = self.options.stdout
72        stderr = self.options.stderr
73        resp = do_http("GET", url)
74        if resp.status != 200:
75            print(format_http_error("ERROR", resp), file=stderr)
76            return True
77        jdata = resp.read()
78        data = json.loads(jdata)
79        if not data["finished"]:
80            return False
81        if self.options.get("raw"):
82            stdout = stdout.buffer
83            if is_printable_ascii(jdata):
84                stdout.write(jdata)
85                stdout.write(b"\n")
86                stdout.flush()
87            else:
88                print("The JSON response contained unprintable characters:\n%s" % quote_output(jdata), file=stderr)
89            return True
90        self.write_results(data)
91        return True
92
Note: See TracBrowser for help on using the repository browser.