Coverage for /Users/ajo/work/jumpstarter/jumpstarter/packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py: 31%
48 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-26 15:50 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-26 15:50 +0200
1import time
2from collections.abc import Generator
4import click
6from .common import PowerReading
7from jumpstarter.client import DriverClient
10class PowerClient(DriverClient):
11 def on(self) -> None:
12 """Power on the device."""
13 self.call("on")
15 def off(self) -> None:
16 """Power off the device."""
17 self.call("off")
19 def rescue(self) -> None:
20 self.call("rescue")
22 def cycle(self, wait: int = 2):
23 """Power cycle the device."""
24 self.logger.info("Starting power cycle sequence")
25 self.off()
26 self.logger.info(f"Waiting {wait} seconds...")
27 time.sleep(wait)
28 self.on()
29 self.logger.info("Power cycle sequence complete")
31 def read(self) -> Generator[PowerReading, None, None]:
32 """Read power data from the device."""
34 for v in self.streamingcall("read"):
35 yield PowerReading.model_validate(v, strict=True)
37 def cli(self):
38 @click.group
39 def base():
40 """Generic power"""
41 pass
43 @base.command()
44 def on():
45 """Power on"""
46 self.on()
48 @base.command()
49 def off():
50 """Power off"""
51 self.off()
53 @base.command()
54 @click.option("--wait", "-w", default=2, help="Wait time in seconds between off and on")
55 def cycle(wait):
56 """Power cycle"""
57 click.echo(f"Power cycling with {wait} seconds wait time...")
58 self.cycle(wait)
60 return base
63class VirtualPowerClient(PowerClient):
64 def off(self, destroy: bool = False) -> None:
65 self.call('off', destroy)
67 def cli(self):
68 parent = super().cli()
70 @parent.command(name='off')
71 @click.option('--destroy', is_flag=True, help='destroy the instance after powering it off')
72 def off(destroy: bool):
73 """Power off"""
74 self.off(destroy)
76 return parent