(call: ServiceCall)
| 29 | default = config.get(DOMAIN) or DEFAULT_SCHEMA({}) |
| 30 | |
| 31 | def exec_command(call: ServiceCall) -> dict: |
| 32 | kwargs = default | call.data |
| 33 | kwargs["hostname"] = kwargs.pop("host") |
| 34 | kwargs["username"] = kwargs.pop("user") |
| 35 | kwargs["password"] = kwargs.pop("pass", None) |
| 36 | kwargs["key_filename"] = kwargs.pop("private_key", None) |
| 37 | |
| 38 | commands = kwargs.pop("command") |
| 39 | if isinstance(commands, str): |
| 40 | commands = [commands] |
| 41 | |
| 42 | client = SSHClient() |
| 43 | client.set_missing_host_key_policy(AutoAddPolicy()) |
| 44 | |
| 45 | try: |
| 46 | client.connect(**kwargs) |
| 47 | |
| 48 | for command in commands: |
| 49 | _, stdout, stderr = client.exec_command( |
| 50 | command, timeout=kwargs.get("timeout") |
| 51 | ) |
| 52 | |
| 53 | # noinspection PyUnboundLocalVariable |
| 54 | return { |
| 55 | "stdout": stdout.read().decode("utf-8"), |
| 56 | "stderr": stderr.read().decode("utf-8"), |
| 57 | } |
| 58 | |
| 59 | except TimeoutError as e: |
| 60 | _LOGGER.error(f"Command execution timeout") |
| 61 | return {"error": repr(e)} |
| 62 | |
| 63 | except Exception as e: |
| 64 | _LOGGER.error(f"Failed to connect: {repr(e)}") |
| 65 | return {"error": repr(e)} |
| 66 | |
| 67 | finally: |
| 68 | client.close() |
| 69 | |
| 70 | try: |
| 71 | # ServiceResponse from Hass 2023.7 |
nothing calls this directly
no outgoing calls
no test coverage detected