def checksshcommand(ui, url, opts): rui = hg.remoteui(ui, opts) sshcmd = rui.config("ui", "ssh") sshaddenv = dict(rui.configitems("sshenv")) sshenv = util.shellenviron(sshaddenv) args = util.sshargs(sshcmd, url.host, url.user, url.port) cmd = "%s %s %s" % (sshcmd, args, "hostname") ui.status( _("Testing SSH connection to the server: running 'hostname'\n"), component="debugnetwork", ) ui.pushbuffer(subproc=True) starttime = util.timer() res = ui.system(cmd, blockedtag="debugnetwork", environ=sshenv) endtime = util.timer() hostname = pycompat.decodeutf8(ui.popbufferbytes()).strip() if res == 0: ui.status( _("Connected ok: %s\n") % util.timecount(endtime - starttime), component="debugnetwork", ) ui.status(_("Server hostname is %s\n") % hostname, component="debugnetwork") return True else: ui.status(_("Failed to connect: ssh returned %s\n") % res, error=_("error")) return False
def run_command(self, host, command, username=None, port=None): if isinstance(command, (str, bytes)): # 0.12.x dulwich sends the raw string command = [command] elif len(command) > 1: # 0.11.x dulwich sends an array of [command arg1 arg2 ...], so # we detect that here and reformat it back to what hg-git # expects (e.g. "command 'arg1 arg2'") command = ["%s '%s'" % (command[0], " ".join(command[1:]))] sshcmd = ui.config("ui", "ssh") args = util.sshargs(sshcmd, host, username, port) cmd = "%s %s %s" % (sshcmd, args, util.shellquote( " ".join(command))) ui.debug("calling ssh: %s\n" % cmd) proc = subprocess.Popen( util.quotecommand(cmd), shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, ) return SubprocessWrapper(proc)
def checkhgspeed(ui, url, opts): speedcmd = ui.config("debugnetwork", "speed-test-command") if speedcmd is None: ui.status( _("Not testing connection speed: 'debugnetwork.speed-test-command' is not set" ), component="debugnetwork", ) return True ui.status(_("Testing connection speed to the server\n"), component="debugnetwork") rui = hg.remoteui(ui, opts) sshcmd = rui.config("ui", "ssh") sshaddenv = dict(rui.configitems("sshenv")) sshenv = util.shellenviron(sshaddenv) args = util.sshargs(sshcmd, url.host, url.user, url.port) download = ui.configbytes("debugnetwork", "speed-test-download-size", 10000000) upload = ui.configbytes("debugnetwork", "speed-test-upload-size", 1000000) cmd = "%s %s %s" % (sshcmd, args, util.shellquote(sshpeer._serverquote(speedcmd))) pipeo, pipei, pipee, sub = util.popen4(cmd, bufsize=0, env=sshenv) pipee = sshpeer.threadedstderr(rui, pipee) pipee.start() def latencytest(count): # Use the upload endpoint for the latency test. We will time how long it # takes for the server to return the "upload complete" response for a # single byte upload. latencies = [] with progress.spinner(ui, "testing connection latency"): for i in range(count): pipeo.write(b"upload 1\n") pipeo.flush() l = pipei.readline() if l != b"upload bytes 1\n": raise error.Abort("invalid response from server: %r" % l) starttime = util.timer() pipeo.write(b"\n") pipeo.flush() l = pipei.readline() endtime = util.timer() if l != b"upload complete\n": raise error.Abort("invalid response from server: %r" % l) latencies.append(endtime - starttime) return latencies def downloadtest(description, bytecount): pipeo.write(b"download %i\n" % bytecount) pipeo.flush() l = pipei.readline() if not l or not l.startswith(b"download bytes"): raise error.Abort("invalid response from server: %r" % l) bytecount = int(l.split()[2]) with progress.bar(ui, description, total=bytecount, formatfunc=util.bytecount) as prog: starttime = util.timer() remaining = bytecount while remaining > 0: data = pipei.read(min(remaining, BLOCK_SIZE)) if not data: raise error.Abort( "premature end of speed-test download stream") remaining -= len(data) prog.value = bytecount - remaining l = pipei.readline() if not l or not l.startswith(b"download complete"): raise error.Abort("invalid response from server: %r" % l) endtime = util.timer() return endtime - starttime def uploadtest(description, bytecount): pipeo.write(b"upload %i\n" % bytecount) pipeo.flush() l = pipei.readline() if not l or not l.startswith(b"upload bytes"): raise error.Abort("invalid response from server: %r" % l) bytecount = int(l.split()[2]) with progress.bar(ui, description, total=bytecount, formatfunc=util.bytecount) as prog: starttime = util.timer() remaining = bytecount while remaining > 0: data = os.urandom(min(remaining, BLOCK_SIZE)) remaining -= len(data) pipeo.write(data) prog.value = bytecount - remaining pipeo.flush() l = pipei.readline() if not l or not l.startswith(b"upload complete"): raise error.Abort("invalid response from server: %r" % l) endtime = util.timer() return endtime - starttime return drivespeedtests( ui, (latencytest, 5), (downloadtest, "download", download), (uploadtest, "upload", upload), )
def checkhgspeed(ui, url, opts): speedcmd = ui.config("debugnetwork", "speed-test-command") if speedcmd is None: ui.status( _("Not testing connection speed: 'debugnetwork.speed-test-command' is not set" ), component="debugnetwork", ) return True ui.status(_("Testing connection speed to the server\n"), component="debugnetwork") rui = hg.remoteui(ui, opts) sshcmd = rui.config("ui", "ssh") sshaddenv = dict(rui.configitems("sshenv")) sshenv = util.shellenviron(sshaddenv) args = util.sshargs(sshcmd, url.host, url.user, url.port) download = ui.configbytes("debugnetwork", "speed-test-download-size", 10000000) upload = ui.configbytes("debugnetwork", "speed-test-upload-size", 1000000) cmd = "%s %s %s" % (sshcmd, args, util.shellquote(sshpeer._serverquote(speedcmd))) pipeo, pipei, pipee, sub = util.popen4(cmd, bufsize=0, env=sshenv) pipee = sshpeer.threadedstderr(rui, pipee) pipee.start() def latencytest(count): # Use the upload endpoint for the latency test. We will time how long it # takes for the server to return the "upload complete" response for a # single byte upload. latencies = [] with progress.spinner(ui, "testing connection latency"): for i in range(count): pipeo.write("upload 1\n") pipeo.flush() l = pipei.readline() if l != "upload bytes 1\n": raise error.Abort("invalid response from server: %r" % l) starttime = util.timer() pipeo.write("\n") pipeo.flush() l = pipei.readline() endtime = util.timer() if l != "upload complete\n": raise error.Abort("invalid response from server: %r" % l) latencies.append(endtime - starttime) return latencies def downloadtest(description, bytecount): pipeo.write("download %s\n" % bytecount) pipeo.flush() l = pipei.readline() if not l or not l.startswith("download bytes"): raise error.Abort("invalid response from server: %r" % l) bytecount = int(l.split()[2]) with progress.bar(ui, description, total=bytecount, formatfunc=util.bytecount) as prog: starttime = util.timer() remaining = bytecount while remaining > 0: data = pipei.read(min(remaining, BLOCK_SIZE)) if not data: raise error.Abort( "premature end of speed-test download stream") remaining -= len(data) prog.value = bytecount - remaining l = pipei.readline() if not l or not l.startswith("download complete"): raise error.Abort("invalid response from server: %r" % l) endtime = util.timer() return endtime - starttime def uploadtest(description, bytecount): pipeo.write("upload %s\n" % bytecount) pipeo.flush() l = pipei.readline() if not l or not l.startswith("upload bytes"): raise error.Abort("invalid response from server: %r" % l) bytecount = int(l.split()[2]) with progress.bar(ui, description, total=bytecount, formatfunc=util.bytecount) as prog: starttime = util.timer() remaining = bytecount while remaining > 0: data = os.urandom(min(remaining, BLOCK_SIZE)) remaining -= len(data) pipeo.write(data) prog.value = bytecount - remaining pipeo.flush() l = pipei.readline() if not l or not l.startswith("upload complete"): raise error.Abort("invalid response from server: %r" % l) endtime = util.timer() return endtime - starttime def printresult(testname, bytecount, testtime): byterate = bytecount / testtime ui.status( _("Speed: %s %s in %s (%0.2f Mbit/s, %0.2f MiB/s)\n") % ( testname, util.bytecount(bytecount), util.timecount(testtime), 8 * byterate / 1000000, byterate / (1024 * 1024), ), component="debugnetwork", ) try: latencies = latencytest(5) latency = sum(latencies, 0) / len(latencies) ui.status( _("Latency: %s (average of %s round-trips)\n") % (util.timecount(latency), len(latencies)), component="debugnetwork", ) for testfunc, testname, bytecount in [ (downloadtest, "download", download), (uploadtest, "upload", upload), ]: warmuptime = testfunc("warming up for %s test" % testname, bytecount) if warmuptime < 0.2: # The network is sufficiently fast that we warmed up in <200ms. # To make the test more meaningful, increase the size of data # 25x (which should give a maximum test time of 5s). bytecount *= 25 warmuptime = testfunc( "warming up for large %s test" % testname, bytecount) printresult("(round 1) %sed" % testname, bytecount, warmuptime) testtime = testfunc(testname, bytecount) printresult("(round 2) %sed" % testname, bytecount, testtime) return True except Exception: return False