pikvm icon indicating copy to clipboard operation
pikvm copied to clipboard

Allow passing a parameter to the CMD ugpio

Open gapodo opened this issue 2 years ago • 1 comments

The Issue

I am controlling a mini-cluster using one PiKVM (utilizing an HDMI KVM,...). Setting up the commands for switching the inputs, controlling node power,... gets fairly repetitive and would be easily parametrized.

Partial `override.yaml` as an example
    gpio:
        drivers:
            kvm1:
                type: cmd
                cmd: [/bin/env,bash,/usr/local/bin/switch_hdmi,1]

            # [...]

            kvm8:
                type: cmd
                cmd: [/bin/env,bash,/usr/local/bin/switch_hdmi,8]
            amt_node01_on:
                type: cmd
                cmd: [/bin/env,bash,/usr/local/bin/amt_power,on,192.168.181.101]
            amt_node01_off:
                type: cmd
                cmd: [/bin/env,bash,/usr/local/bin/amt_power,off,192.168.181.101]
            amt_node01_reset:
                type: cmd
                cmd: [/bin/env,bash,/usr/local/bin/amt_power,reset,192.168.181.101]
            amt_node01_cycle:
                type: cmd
                cmd: [/bin/env,bash,/usr/local/bin/amt_power,cycle,192.168.181.101]

            # [...]

            amt_node08_on:
                type: cmd
                cmd: [/bin/env,bash,/usr/local/bin/amt_power,on,192.168.181.108]
            amt_node08_off:
                type: cmd
                cmd: [/bin/env,bash,/usr/local/bin/amt_power,off,192.168.181.108]
            amt_node08_reset:
                type: cmd
                cmd: [/bin/env,bash,/usr/local/bin/amt_power,reset,192.168.181.108]
            amt_node08_cycle:
                type: cmd
                cmd: [/bin/env,bash,/usr/local/bin/amt_power,cycle,192.168.181.108]

        scheme:
            kvm1_button:
                driver: kvm1
                pin: 1
                mode: output
                switch: false
            
            # [...]
            
            kvm8_button:
                driver: kvm8
                pin: 8
                mode: output
                switch: false

            amt_node01_on_button:
                driver: amt_node01_on
                pin: 9
                mode: output
                switch: false
            amt_node01_off_button:
                driver: amt_node01_off
                pin: 10
                mode: output
                switch: false
            amt_node01_reset_button:
                driver: amt_node01_reset
                pin: 11
                mode: output
                switch: false
            amt_node01_cycle_button:
                driver: amt_node01_cycle
                pin: 12
                mode: output
                switch: false
            
            # [...]
            
            amt_node08_on_button:
                driver: amt_node08_on
                pin: 37
                mode: output
                switch: false
            amt_node08_off_button:
                driver: amt_node08_off
                pin: 38
                mode: output
                switch: false
            amt_node08_reset_button:
                driver: amt_node08_reset
                pin: 39
                mode: output
                switch: false
            amt_node08_cycle_button:
                driver: amt_node08_cycle
                pin: 40
                mode: output
                switch: false

Proposed solution

Since the aioproc.log_process already has the ability to set environment variables, I'd introduce the kvmd_pin env to the commands called (in cmd.py and cmdret.py), this would not break existing calls, as this variable didn't exist before and is not supplied as a positional argument. This would allow writing either wrappers or adjust scripts to allow fetching data from the env variable.

While the pin only allows for a string, one could supply a quoted json, csv,... and split it in the wrapper or script.

Partial `override.yaml`, utilizing the proposed change
    gpio:
        drivers:
            kvm:
                type: cmd
                cmd: [/bin/env,bash,/usr/local/bin/switch_hdmi]

            amt_power:
                type: cmd
                cmd: [/bin/env,bash,/usr/local/bin/amt_power]

        scheme:
            kvm1_button:
                driver: kvm
                pin: 1
                mode: output
                switch: false
            
            # [...]
            
            kvm8_button:
                driver: kvm
                pin: 8
                mode: output
                switch: false

            amt_node01_on_button:
                driver: amt_power
                pin: "on,192.168.181.101"
                mode: output
                switch: false
            amt_node01_off_button:
                driver: amt_power
                pin: "off,192.168.181.101"
                mode: output
                switch: false
            amt_node01_reset_button:
                driver: amt_power
                pin: "reset,192.168.181.101"
                mode: output
                switch: false
            amt_node01_cycle_button:
                driver: amt_power
                pin: "cycle,192.168.181.101"
                mode: output
                switch: false
            
            # [...]

            amt_node08_on_button:
                driver: amt_power
                pin: "on,192.168.181.108"
                mode: output
                switch: false
            amt_node08_off_button:
                driver: amt_power
                pin: "off,192.168.181.108"
                mode: output
                switch: false
            amt_node08_reset_button:
                driver: amt_power
                pin: "reset,192.168.181.108"
                mode: output
                switch: false
            amt_node08_cycle_button:
                driver: amt_power
                pin: "cycle,192.168.181.108"
                mode: output
                switch: false

The implementation requires a 2 line change in cmd.py and cmdret.py one removing the _ = pin and adding env={ "kvmd_pin": pin }, to proc = await aioproc.log_process(self.__cmd, logger=get_logger(0), prefix=str(self)) arguments.

One advantage of supplying "everything" in the kvmd_pin env is, that it prevents potentaially hard to diagnose issues with overridden standard envs / name collisions.

Alternative solution

It may be possible to extend the ugpio implementation to allow for extra parameters,... though that is way above my python capabilities... and would likely require a major redesign / refactor (without being a python programmer it appears to me that the individual plugins are basically implementations of an interface?)

Meta

If the proposed solution is somewhat interesting / acceptable, I'd be happy to supply the PR, I've already tested it on my system, and it takes away a lot of repetition in the kvmd.gpio.drivers section of the override.yaml, helping to keep it manageable.

gapodo avatar Apr 01 '23 19:04 gapodo

Hello. Right now, the gpio mechanism does not allow to implement something like this due to API limitations. I'll think about what can be done with it, but I can't promise that it will be fast.

mdevaev avatar Apr 14 '23 03:04 mdevaev