Run a bandwidth test. Supports both the Ookla `speedtest` CLI and the python `speedtest-cli`; returns download/upload in Mbps.
()
| 190 | 'error': f'Source {source} is not a local address on this host ' |
| 191 | f'(mtr can only originate from a local IP). Valid: {valid}'} |
| 192 | cmd += ['-a', source] |
| 193 | cmd += ['-j', target] |
| 194 | res = _run(cmd, timeout=count * 3 + 15) |
| 195 | if res['rc'] == 127: |
| 196 | return {'success': False, |
| 197 | 'error': 'mtr is not installed. Click Install to add it.', |
| 198 | 'missing_tool': 'mtr'} |
| 199 | hops = [] |
| 200 | try: |
| 201 | data = json.loads(res['out']) |
| 202 | for h in data.get('report', {}).get('hubs', []): |
| 203 | hops.append({ |
| 204 | 'hop': h.get('count'), |
| 205 | 'host': h.get('host'), |
| 206 | 'loss_pct': h.get('Loss%'), |
| 207 | 'sent': h.get('Snt'), |
| 208 | 'last': h.get('Last'), |
| 209 | 'avg': h.get('Avg'), |
| 210 | 'best': h.get('Best'), |
| 211 | 'worst': h.get('Wrst'), |
| 212 | 'stdev': h.get('StDev'), |
| 213 | }) |
| 214 | return {'success': True, 'hops': hops} |
| 215 | except (ValueError, KeyError) as e: |
| 216 | return {'success': False, 'error': f'could not parse mtr output: {e}', |
| 217 | 'output': res['out'] or res['err']} |
| 218 | |
| 219 | |
| 220 | def do_whois(target): |
| 221 | res = _run(['whois', target], timeout=25) |
| 222 | if res['rc'] == 127: |
| 223 | return {'success': False, 'output': '', |
| 224 | 'error': 'whois is not installed. Click Install to add it.', |
| 225 | 'missing_tool': 'whois'} |
| 226 | return {'success': True, 'output': (res['out'] or res['err']).strip(), 'error': None} |
| 227 | |
| 228 | |
| 229 | def do_ip_intel(target, offline=False): |
| 230 | """Attribute an IP address — country, ASN, network owner, abuse contact. |
| 231 | |
| 232 | Thin wrapper over ip_intel.lookup(); see that module for why no street |
| 233 | address is ever reported. Accepts a hostname too, resolving it first, so the |
| 234 | UI can take either.""" |
| 235 | import ip_intel |
| 236 | ip = str(target).strip() |
| 237 | resolved_from = None |
| 238 | if ip_intel.ip_scope(ip)[0] == 'invalid': |
| 239 | try: # maybe it's a hostname |
no test coverage detected