eeroctl 1.7.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eeroctl/__init__.py +19 -0
- eeroctl/commands/__init__.py +32 -0
- eeroctl/commands/activity.py +237 -0
- eeroctl/commands/auth.py +471 -0
- eeroctl/commands/completion.py +142 -0
- eeroctl/commands/device.py +492 -0
- eeroctl/commands/eero/__init__.py +12 -0
- eeroctl/commands/eero/base.py +224 -0
- eeroctl/commands/eero/led.py +154 -0
- eeroctl/commands/eero/nightlight.py +235 -0
- eeroctl/commands/eero/updates.py +82 -0
- eeroctl/commands/network/__init__.py +18 -0
- eeroctl/commands/network/advanced.py +191 -0
- eeroctl/commands/network/backup.py +162 -0
- eeroctl/commands/network/base.py +331 -0
- eeroctl/commands/network/dhcp.py +118 -0
- eeroctl/commands/network/dns.py +197 -0
- eeroctl/commands/network/forwards.py +115 -0
- eeroctl/commands/network/guest.py +162 -0
- eeroctl/commands/network/security.py +162 -0
- eeroctl/commands/network/speedtest.py +99 -0
- eeroctl/commands/network/sqm.py +194 -0
- eeroctl/commands/profile.py +671 -0
- eeroctl/commands/troubleshoot.py +317 -0
- eeroctl/context.py +254 -0
- eeroctl/errors.py +156 -0
- eeroctl/exit_codes.py +68 -0
- eeroctl/formatting/__init__.py +90 -0
- eeroctl/formatting/base.py +181 -0
- eeroctl/formatting/device.py +430 -0
- eeroctl/formatting/eero.py +591 -0
- eeroctl/formatting/misc.py +87 -0
- eeroctl/formatting/network.py +659 -0
- eeroctl/formatting/profile.py +443 -0
- eeroctl/main.py +161 -0
- eeroctl/options.py +429 -0
- eeroctl/output.py +739 -0
- eeroctl/safety.py +259 -0
- eeroctl/utils.py +181 -0
- eeroctl-1.7.1.dist-info/METADATA +115 -0
- eeroctl-1.7.1.dist-info/RECORD +45 -0
- eeroctl-1.7.1.dist-info/WHEEL +5 -0
- eeroctl-1.7.1.dist-info/entry_points.txt +3 -0
- eeroctl-1.7.1.dist-info/licenses/LICENSE +21 -0
- eeroctl-1.7.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""Security commands for the Eero CLI.
|
|
2
|
+
|
|
3
|
+
Commands:
|
|
4
|
+
- eero network security show: Show security settings
|
|
5
|
+
- eero network security wpa3: WPA3 encryption
|
|
6
|
+
- eero network security band-steering: Band steering
|
|
7
|
+
- eero network security upnp: UPnP
|
|
8
|
+
- eero network security ipv6: IPv6
|
|
9
|
+
- eero network security thread: Thread protocol
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import asyncio
|
|
13
|
+
import sys
|
|
14
|
+
|
|
15
|
+
import click
|
|
16
|
+
from eero import EeroClient
|
|
17
|
+
from rich.table import Table
|
|
18
|
+
|
|
19
|
+
from ...context import get_cli_context
|
|
20
|
+
from ...exit_codes import ExitCode
|
|
21
|
+
from ...safety import OperationRisk, SafetyError, confirm_or_fail
|
|
22
|
+
from ...utils import run_with_client
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@click.group(name="security")
|
|
26
|
+
@click.pass_context
|
|
27
|
+
def security_group(ctx: click.Context) -> None:
|
|
28
|
+
"""Manage security settings.
|
|
29
|
+
|
|
30
|
+
\b
|
|
31
|
+
Commands:
|
|
32
|
+
show - Show security settings
|
|
33
|
+
wpa3 - WPA3 encryption
|
|
34
|
+
band-steering - Band steering
|
|
35
|
+
upnp - UPnP
|
|
36
|
+
ipv6 - IPv6
|
|
37
|
+
thread - Thread protocol
|
|
38
|
+
|
|
39
|
+
\b
|
|
40
|
+
Examples:
|
|
41
|
+
eero network security show
|
|
42
|
+
eero network security wpa3 enable
|
|
43
|
+
eero network security upnp disable
|
|
44
|
+
"""
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@security_group.command(name="show")
|
|
49
|
+
@click.pass_context
|
|
50
|
+
def security_show(ctx: click.Context) -> None:
|
|
51
|
+
"""Show security settings."""
|
|
52
|
+
cli_ctx = get_cli_context(ctx)
|
|
53
|
+
console = cli_ctx.console
|
|
54
|
+
renderer = cli_ctx.renderer
|
|
55
|
+
|
|
56
|
+
async def run_cmd() -> None:
|
|
57
|
+
async def get_security(client: EeroClient) -> None:
|
|
58
|
+
with cli_ctx.status("Getting security settings..."):
|
|
59
|
+
sec_data = await client.get_security_settings(cli_ctx.network_id)
|
|
60
|
+
|
|
61
|
+
if cli_ctx.is_json_output():
|
|
62
|
+
renderer.render_json(sec_data, "eero.network.security.show/v1")
|
|
63
|
+
else:
|
|
64
|
+
table = Table(title="Security Settings")
|
|
65
|
+
table.add_column("Setting", style="cyan")
|
|
66
|
+
table.add_column("Status", justify="center")
|
|
67
|
+
|
|
68
|
+
settings = [
|
|
69
|
+
("WPA3", sec_data.get("wpa3", False)),
|
|
70
|
+
("Band Steering", sec_data.get("band_steering", True)),
|
|
71
|
+
("UPnP", sec_data.get("upnp", True)),
|
|
72
|
+
("IPv6", sec_data.get("ipv6_upstream", False)),
|
|
73
|
+
("Thread", sec_data.get("thread", False)),
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
for name, enabled in settings:
|
|
77
|
+
status = "[green]Enabled[/green]" if enabled else "[dim]Disabled[/dim]"
|
|
78
|
+
table.add_row(name, status)
|
|
79
|
+
|
|
80
|
+
console.print(table)
|
|
81
|
+
|
|
82
|
+
await run_with_client(get_security)
|
|
83
|
+
|
|
84
|
+
asyncio.run(run_cmd())
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# Security toggle commands factory
|
|
88
|
+
def _make_security_toggle(setting_name: str, api_method: str, display_name: str):
|
|
89
|
+
"""Factory for security toggle command groups."""
|
|
90
|
+
|
|
91
|
+
@click.group(name=setting_name)
|
|
92
|
+
@click.pass_context
|
|
93
|
+
def toggle_group(ctx: click.Context) -> None:
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
@toggle_group.command(name="enable")
|
|
97
|
+
@click.option("--force", "-f", is_flag=True, help="Skip confirmation")
|
|
98
|
+
@click.pass_context
|
|
99
|
+
def enable_cmd(ctx: click.Context, force: bool) -> None:
|
|
100
|
+
_set_security_setting(ctx, api_method, display_name, True, force)
|
|
101
|
+
|
|
102
|
+
@toggle_group.command(name="disable")
|
|
103
|
+
@click.option("--force", "-f", is_flag=True, help="Skip confirmation")
|
|
104
|
+
@click.pass_context
|
|
105
|
+
def disable_cmd(ctx: click.Context, force: bool) -> None:
|
|
106
|
+
_set_security_setting(ctx, api_method, display_name, False, force)
|
|
107
|
+
|
|
108
|
+
enable_cmd.__doc__ = f"Enable {display_name}."
|
|
109
|
+
disable_cmd.__doc__ = f"Disable {display_name}."
|
|
110
|
+
toggle_group.__doc__ = f"Manage {display_name}."
|
|
111
|
+
|
|
112
|
+
return toggle_group
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _set_security_setting(ctx, api_method: str, display_name: str, enable: bool, force: bool):
|
|
116
|
+
"""Set a security setting."""
|
|
117
|
+
cli_ctx = get_cli_context(ctx)
|
|
118
|
+
console = cli_ctx.console
|
|
119
|
+
action = "enable" if enable else "disable"
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
confirm_or_fail(
|
|
123
|
+
action=f"{action} {display_name}",
|
|
124
|
+
target="network",
|
|
125
|
+
risk=OperationRisk.MEDIUM,
|
|
126
|
+
force=force or cli_ctx.force,
|
|
127
|
+
non_interactive=cli_ctx.non_interactive,
|
|
128
|
+
dry_run=cli_ctx.dry_run,
|
|
129
|
+
)
|
|
130
|
+
except SafetyError as e:
|
|
131
|
+
cli_ctx.renderer.render_error(e.message)
|
|
132
|
+
sys.exit(e.exit_code)
|
|
133
|
+
|
|
134
|
+
async def run_cmd() -> None:
|
|
135
|
+
async def set_setting(client: EeroClient) -> None:
|
|
136
|
+
method = getattr(client, api_method)
|
|
137
|
+
with cli_ctx.status(f"{action.capitalize()}ing {display_name}..."):
|
|
138
|
+
result = await method(enable, cli_ctx.network_id)
|
|
139
|
+
|
|
140
|
+
if result:
|
|
141
|
+
console.print(f"[bold green]{display_name} {action}d[/bold green]")
|
|
142
|
+
else:
|
|
143
|
+
console.print(f"[red]Failed to {action} {display_name}[/red]")
|
|
144
|
+
sys.exit(ExitCode.GENERIC_ERROR)
|
|
145
|
+
|
|
146
|
+
await run_with_client(set_setting)
|
|
147
|
+
|
|
148
|
+
asyncio.run(run_cmd())
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
# Create and register security toggle commands
|
|
152
|
+
wpa3_group = _make_security_toggle("wpa3", "set_wpa3", "WPA3")
|
|
153
|
+
band_steering_group = _make_security_toggle("band-steering", "set_band_steering", "band steering")
|
|
154
|
+
upnp_group = _make_security_toggle("upnp", "set_upnp", "UPnP")
|
|
155
|
+
ipv6_group = _make_security_toggle("ipv6", "set_ipv6", "IPv6")
|
|
156
|
+
thread_group = _make_security_toggle("thread", "set_thread_enabled", "Thread")
|
|
157
|
+
|
|
158
|
+
security_group.add_command(wpa3_group)
|
|
159
|
+
security_group.add_command(band_steering_group)
|
|
160
|
+
security_group.add_command(upnp_group)
|
|
161
|
+
security_group.add_command(ipv6_group)
|
|
162
|
+
security_group.add_command(thread_group)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Speed test commands for the Eero CLI.
|
|
2
|
+
|
|
3
|
+
Commands:
|
|
4
|
+
- eero network speedtest run: Run a new speed test
|
|
5
|
+
- eero network speedtest show: Show last speed test results
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
|
|
10
|
+
import click
|
|
11
|
+
from eero import EeroClient
|
|
12
|
+
from rich.panel import Panel
|
|
13
|
+
|
|
14
|
+
from ...context import get_cli_context
|
|
15
|
+
from ...utils import run_with_client
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@click.group(name="speedtest")
|
|
19
|
+
@click.pass_context
|
|
20
|
+
def speedtest_group(ctx: click.Context) -> None:
|
|
21
|
+
"""Run and view speed tests.
|
|
22
|
+
|
|
23
|
+
\b
|
|
24
|
+
Commands:
|
|
25
|
+
run - Run a new speed test
|
|
26
|
+
show - Show last speed test results
|
|
27
|
+
"""
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@speedtest_group.command(name="run")
|
|
32
|
+
@click.pass_context
|
|
33
|
+
def speedtest_run(ctx: click.Context) -> None:
|
|
34
|
+
"""Run a new speed test."""
|
|
35
|
+
cli_ctx = get_cli_context(ctx)
|
|
36
|
+
console = cli_ctx.console
|
|
37
|
+
renderer = cli_ctx.renderer
|
|
38
|
+
|
|
39
|
+
async def run_cmd() -> None:
|
|
40
|
+
async def run_test(client: EeroClient) -> None:
|
|
41
|
+
with cli_ctx.status("Running speed test (this may take a minute)..."):
|
|
42
|
+
result = await client.run_speed_test(cli_ctx.network_id)
|
|
43
|
+
|
|
44
|
+
if cli_ctx.is_json_output():
|
|
45
|
+
renderer.render_json(result, "eero.network.speedtest.run/v1")
|
|
46
|
+
else:
|
|
47
|
+
download = result.get("down", {}).get("value", 0)
|
|
48
|
+
upload = result.get("up", {}).get("value", 0)
|
|
49
|
+
latency = result.get("latency", {}).get("value", 0)
|
|
50
|
+
|
|
51
|
+
content = (
|
|
52
|
+
f"[bold]Download:[/bold] {download} Mbps\n"
|
|
53
|
+
f"[bold]Upload:[/bold] {upload} Mbps\n"
|
|
54
|
+
f"[bold]Latency:[/bold] {latency} ms"
|
|
55
|
+
)
|
|
56
|
+
console.print(Panel(content, title="Speed Test Results", border_style="green"))
|
|
57
|
+
|
|
58
|
+
await run_with_client(run_test)
|
|
59
|
+
|
|
60
|
+
asyncio.run(run_cmd())
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@speedtest_group.command(name="show")
|
|
64
|
+
@click.pass_context
|
|
65
|
+
def speedtest_show(ctx: click.Context) -> None:
|
|
66
|
+
"""Show last speed test results."""
|
|
67
|
+
cli_ctx = get_cli_context(ctx)
|
|
68
|
+
console = cli_ctx.console
|
|
69
|
+
renderer = cli_ctx.renderer
|
|
70
|
+
|
|
71
|
+
async def run_cmd() -> None:
|
|
72
|
+
async def get_results(client: EeroClient) -> None:
|
|
73
|
+
with cli_ctx.status("Getting speed test results..."):
|
|
74
|
+
network = await client.get_network(cli_ctx.network_id)
|
|
75
|
+
|
|
76
|
+
speed_test = network.speed_test
|
|
77
|
+
if not speed_test:
|
|
78
|
+
console.print("[yellow]No speed test results available[/yellow]")
|
|
79
|
+
return
|
|
80
|
+
|
|
81
|
+
if cli_ctx.is_json_output():
|
|
82
|
+
renderer.render_json(speed_test, "eero.network.speedtest.show/v1")
|
|
83
|
+
else:
|
|
84
|
+
download = speed_test.get("down", {}).get("value", 0)
|
|
85
|
+
upload = speed_test.get("up", {}).get("value", 0)
|
|
86
|
+
latency = speed_test.get("latency", {}).get("value", 0)
|
|
87
|
+
tested = speed_test.get("date", "Unknown")
|
|
88
|
+
|
|
89
|
+
content = (
|
|
90
|
+
f"[bold]Download:[/bold] {download} Mbps\n"
|
|
91
|
+
f"[bold]Upload:[/bold] {upload} Mbps\n"
|
|
92
|
+
f"[bold]Latency:[/bold] {latency} ms\n"
|
|
93
|
+
f"[bold]Tested:[/bold] {tested}"
|
|
94
|
+
)
|
|
95
|
+
console.print(Panel(content, title="Speed Test Results", border_style="blue"))
|
|
96
|
+
|
|
97
|
+
await run_with_client(get_results)
|
|
98
|
+
|
|
99
|
+
asyncio.run(run_cmd())
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""SQM (Smart Queue Management) commands for the Eero CLI.
|
|
2
|
+
|
|
3
|
+
Commands:
|
|
4
|
+
- eero network sqm show: Show SQM settings
|
|
5
|
+
- eero network sqm enable: Enable SQM
|
|
6
|
+
- eero network sqm disable: Disable SQM
|
|
7
|
+
- eero network sqm set: Configure bandwidth limits
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
import sys
|
|
12
|
+
from typing import Optional
|
|
13
|
+
|
|
14
|
+
import click
|
|
15
|
+
from eero import EeroClient
|
|
16
|
+
from rich.panel import Panel
|
|
17
|
+
|
|
18
|
+
from ...context import EeroCliContext, get_cli_context
|
|
19
|
+
from ...exit_codes import ExitCode
|
|
20
|
+
from ...safety import OperationRisk, SafetyError, confirm_or_fail
|
|
21
|
+
from ...utils import run_with_client
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@click.group(name="sqm")
|
|
25
|
+
@click.pass_context
|
|
26
|
+
def sqm_group(ctx: click.Context) -> None:
|
|
27
|
+
"""Manage Smart Queue Management (SQM) / QoS settings.
|
|
28
|
+
|
|
29
|
+
\b
|
|
30
|
+
Commands:
|
|
31
|
+
show - Show SQM settings
|
|
32
|
+
enable - Enable SQM
|
|
33
|
+
disable - Disable SQM
|
|
34
|
+
set - Configure bandwidth limits
|
|
35
|
+
|
|
36
|
+
\b
|
|
37
|
+
Examples:
|
|
38
|
+
eero network sqm show
|
|
39
|
+
eero network sqm enable
|
|
40
|
+
eero network sqm set --upload 50 --download 200
|
|
41
|
+
"""
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@sqm_group.command(name="show")
|
|
46
|
+
@click.pass_context
|
|
47
|
+
def sqm_show(ctx: click.Context) -> None:
|
|
48
|
+
"""Show SQM settings."""
|
|
49
|
+
cli_ctx = get_cli_context(ctx)
|
|
50
|
+
console = cli_ctx.console
|
|
51
|
+
renderer = cli_ctx.renderer
|
|
52
|
+
|
|
53
|
+
async def run_cmd() -> None:
|
|
54
|
+
async def get_sqm(client: EeroClient) -> None:
|
|
55
|
+
with cli_ctx.status("Getting SQM settings..."):
|
|
56
|
+
sqm_data = await client.get_sqm_settings(cli_ctx.network_id)
|
|
57
|
+
|
|
58
|
+
if cli_ctx.is_json_output():
|
|
59
|
+
renderer.render_json(sqm_data, "eero.network.sqm.show/v1")
|
|
60
|
+
else:
|
|
61
|
+
enabled = sqm_data.get("enabled", False)
|
|
62
|
+
upload_bw = sqm_data.get("upload_bandwidth")
|
|
63
|
+
download_bw = sqm_data.get("download_bandwidth")
|
|
64
|
+
|
|
65
|
+
content = (
|
|
66
|
+
f"[bold]Enabled:[/bold] {'[green]Yes[/green]' if enabled else '[dim]No[/dim]'}"
|
|
67
|
+
)
|
|
68
|
+
if upload_bw:
|
|
69
|
+
content += f"\n[bold]Upload:[/bold] {upload_bw} Mbps"
|
|
70
|
+
if download_bw:
|
|
71
|
+
content += f"\n[bold]Download:[/bold] {download_bw} Mbps"
|
|
72
|
+
|
|
73
|
+
console.print(Panel(content, title="SQM Settings", border_style="blue"))
|
|
74
|
+
|
|
75
|
+
await run_with_client(get_sqm)
|
|
76
|
+
|
|
77
|
+
asyncio.run(run_cmd())
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@sqm_group.command(name="enable")
|
|
81
|
+
@click.option("--force", "-f", is_flag=True, help="Skip confirmation")
|
|
82
|
+
@click.pass_context
|
|
83
|
+
def sqm_enable(ctx: click.Context, force: bool) -> None:
|
|
84
|
+
"""Enable SQM."""
|
|
85
|
+
cli_ctx = get_cli_context(ctx)
|
|
86
|
+
_set_sqm_enabled(cli_ctx, True, force)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@sqm_group.command(name="disable")
|
|
90
|
+
@click.option("--force", "-f", is_flag=True, help="Skip confirmation")
|
|
91
|
+
@click.pass_context
|
|
92
|
+
def sqm_disable(ctx: click.Context, force: bool) -> None:
|
|
93
|
+
"""Disable SQM."""
|
|
94
|
+
cli_ctx = get_cli_context(ctx)
|
|
95
|
+
_set_sqm_enabled(cli_ctx, False, force)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _set_sqm_enabled(cli_ctx: EeroCliContext, enable: bool, force: bool) -> None:
|
|
99
|
+
"""Enable or disable SQM."""
|
|
100
|
+
console = cli_ctx.console
|
|
101
|
+
action = "enable" if enable else "disable"
|
|
102
|
+
|
|
103
|
+
try:
|
|
104
|
+
confirm_or_fail(
|
|
105
|
+
action=f"{action} SQM",
|
|
106
|
+
target="network",
|
|
107
|
+
risk=OperationRisk.MEDIUM,
|
|
108
|
+
force=force or cli_ctx.force,
|
|
109
|
+
non_interactive=cli_ctx.non_interactive,
|
|
110
|
+
dry_run=cli_ctx.dry_run,
|
|
111
|
+
)
|
|
112
|
+
except SafetyError as e:
|
|
113
|
+
cli_ctx.renderer.render_error(e.message)
|
|
114
|
+
sys.exit(e.exit_code)
|
|
115
|
+
|
|
116
|
+
async def run_cmd() -> None:
|
|
117
|
+
async def set_sqm(client: EeroClient) -> None:
|
|
118
|
+
with cli_ctx.status(f"{action.capitalize()}ing SQM..."):
|
|
119
|
+
result = await client.set_sqm_enabled(enable, cli_ctx.network_id)
|
|
120
|
+
|
|
121
|
+
if result:
|
|
122
|
+
console.print(f"[bold green]SQM {action}d[/bold green]")
|
|
123
|
+
else:
|
|
124
|
+
console.print(f"[red]Failed to {action} SQM[/red]")
|
|
125
|
+
sys.exit(ExitCode.GENERIC_ERROR)
|
|
126
|
+
|
|
127
|
+
await run_with_client(set_sqm)
|
|
128
|
+
|
|
129
|
+
asyncio.run(run_cmd())
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@sqm_group.command(name="set")
|
|
133
|
+
@click.option("--upload", "-u", type=int, help="Upload bandwidth limit (Mbps)")
|
|
134
|
+
@click.option("--download", "-d", type=int, help="Download bandwidth limit (Mbps)")
|
|
135
|
+
@click.option("--force", "-f", is_flag=True, help="Skip confirmation")
|
|
136
|
+
@click.pass_context
|
|
137
|
+
def sqm_set(
|
|
138
|
+
ctx: click.Context, upload: Optional[int], download: Optional[int], force: bool
|
|
139
|
+
) -> None:
|
|
140
|
+
"""Configure SQM bandwidth limits.
|
|
141
|
+
|
|
142
|
+
\b
|
|
143
|
+
Options:
|
|
144
|
+
--upload, -u Upload bandwidth in Mbps
|
|
145
|
+
--download, -d Download bandwidth in Mbps
|
|
146
|
+
|
|
147
|
+
\b
|
|
148
|
+
Examples:
|
|
149
|
+
eero network sqm set --upload 50 --download 200
|
|
150
|
+
"""
|
|
151
|
+
cli_ctx = get_cli_context(ctx)
|
|
152
|
+
console = cli_ctx.console
|
|
153
|
+
|
|
154
|
+
if upload is None and download is None:
|
|
155
|
+
console.print("[yellow]Specify --upload and/or --download[/yellow]")
|
|
156
|
+
sys.exit(ExitCode.USAGE_ERROR)
|
|
157
|
+
|
|
158
|
+
try:
|
|
159
|
+
confirm_or_fail(
|
|
160
|
+
action="configure SQM",
|
|
161
|
+
target=f"upload={upload}Mbps download={download}Mbps",
|
|
162
|
+
risk=OperationRisk.MEDIUM,
|
|
163
|
+
force=force or cli_ctx.force,
|
|
164
|
+
non_interactive=cli_ctx.non_interactive,
|
|
165
|
+
dry_run=cli_ctx.dry_run,
|
|
166
|
+
)
|
|
167
|
+
except SafetyError as e:
|
|
168
|
+
cli_ctx.renderer.render_error(e.message)
|
|
169
|
+
sys.exit(e.exit_code)
|
|
170
|
+
|
|
171
|
+
async def run_cmd() -> None:
|
|
172
|
+
async def configure_sqm(client: EeroClient) -> None:
|
|
173
|
+
with cli_ctx.status("Configuring SQM..."):
|
|
174
|
+
result = await client.configure_sqm(
|
|
175
|
+
enabled=True,
|
|
176
|
+
upload_mbps=upload,
|
|
177
|
+
download_mbps=download,
|
|
178
|
+
network_id=cli_ctx.network_id,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
if result:
|
|
182
|
+
msg_parts = []
|
|
183
|
+
if upload:
|
|
184
|
+
msg_parts.append(f"Upload={upload}Mbps")
|
|
185
|
+
if download:
|
|
186
|
+
msg_parts.append(f"Download={download}Mbps")
|
|
187
|
+
console.print(f"[bold green]SQM configured: {' '.join(msg_parts)}[/bold green]")
|
|
188
|
+
else:
|
|
189
|
+
console.print("[red]Failed to configure SQM[/red]")
|
|
190
|
+
sys.exit(ExitCode.GENERIC_ERROR)
|
|
191
|
+
|
|
192
|
+
await run_with_client(configure_sqm)
|
|
193
|
+
|
|
194
|
+
asyncio.run(run_cmd())
|