diff --git a/cmk/base/legacy_checks/agent_ibmsvc.py b/cmk/base/legacy_checks/agent_ibmsvc.py
deleted file mode 100644
index 9e5b3140608..00000000000
--- a/cmk/base/legacy_checks/agent_ibmsvc.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 Checkmk GmbH - License: GNU General Public License v2
-# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
-# conditions defined in the file COPYING, which is part of this source code package.
-
-
-from collections.abc import Mapping, Sequence
-from typing import Any
-
-from cmk.base.config import special_agent_info
-
-
-def agent_ibmsvc_arguments(
- params: Mapping[str, Any], hostname: str, ipaddress: str | None
-) -> Sequence[str]:
- args = ["-u", params["user"], "-i", ",".join(params["infos"])]
- if params["accept-any-hostkey"] is True:
- args += ["--accept-any-hostkey"]
-
- args.append(ipaddress or hostname)
- return args
-
-
-special_agent_info["ibmsvc"] = agent_ibmsvc_arguments
diff --git a/cmk/gui/plugins/wato/special_agents/ibmsvc.py b/cmk/gui/plugins/wato/special_agents/ibmsvc.py
deleted file mode 100644
index 6f02b153013..00000000000
--- a/cmk/gui/plugins/wato/special_agents/ibmsvc.py
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 Checkmk GmbH - License: GNU General Public License v2
-# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
-# conditions defined in the file COPYING, which is part of this source code package.
-
-
-from cmk.utils.rulesets.definition import RuleGroup
-
-from cmk.gui.i18n import _
-from cmk.gui.plugins.wato.utils import HostRulespec, rulespec_registry
-from cmk.gui.valuespec import Checkbox, Dictionary, ListChoice, TextInput
-from cmk.gui.wato import RulespecGroupDatasourceProgramsHardware
-
-
-def _valuespec_special_agents_ibmsvc() -> Dictionary:
- return Dictionary(
- title=_("IBM SVC / V7000 storage systems"),
- help=_(
- "This rule set selects the ibmsvc agent instead of the normal Checkmk Agent "
- "and allows monitoring of IBM SVC / V7000 storage systems by calling "
- "ls* commands there over SSH. "
- "Make sure you have SSH key authentication enabled for your monitoring user. "
- "That means: The user your monitoring is running under on the monitoring "
- "system must be able to ssh to the storage system as the user you gave below "
- "without password."
- ),
- elements=[
- (
- "user",
- TextInput(
- title=_("IBM SVC / V7000 user name"),
- allow_empty=True,
- help=_(
- "User name on the storage system. Read only permissions are sufficient."
- ),
- ),
- ),
- (
- "accept-any-hostkey",
- Checkbox(
- title=_("Accept any SSH Host Key"),
- label=_("Accept any SSH Host Key"),
- default_value=False,
- help=_(
- "Accepts any SSH Host Key presented by the storage device. "
- "Please note: This might be a security issue because man-in-the-middle "
- "attacks are not recognized! Better solution would be to add the "
- "SSH Host Key of the monitored storage devices to the .ssh/known_hosts "
- "file for the user your monitoring is running under (on OMD: the site user)"
- ),
- ),
- ),
- (
- "infos",
- ListChoice(
- title=_("Retrieve information about..."),
- choices=[
- ("lshost", _("Hosts Connected")),
- ("lslicense", _("Licensing Status")),
- ("lsmdisk", _("MDisks")),
- ("lsmdiskgrp", _("MDisksGrps")),
- ("lsnode", _("IO Groups")),
- ("lsnodestats", _("Node Stats")),
- ("lssystem", _("System Info")),
- ("lssystemstats", _("System Stats")),
- ("lseventlog", _("Event Log")),
- ("lsportfc", _("FC Ports")),
- ("lsportsas", _("SAS Ports")),
- ("lsenclosure", _("Enclosures")),
- ("lsenclosurestats", _("Enclosure Stats")),
- ("lsarray", _("RAID Arrays")),
- ("disks", _("Physical Disks")),
- ],
- default_value=[
- "lshost",
- "lslicense",
- "lsmdisk",
- "lsmdiskgrp",
- "lsnode",
- "lsnodestats",
- "lssystem",
- "lssystemstats",
- "lsportfc",
- "lsenclosure",
- "lsenclosurestats",
- "lsarray",
- "disks",
- ],
- allow_empty=False,
- ),
- ),
- ],
- optional_keys=[],
- )
-
-
-rulespec_registry.register(
- HostRulespec(
- group=RulespecGroupDatasourceProgramsHardware,
- name=RuleGroup.SpecialAgents("ibmsvc"),
- valuespec=_valuespec_special_agents_ibmsvc,
- )
-)
diff --git a/cmk/plugins/ibmsvc/rulesets/special_agent.py b/cmk/plugins/ibmsvc/rulesets/special_agent.py
new file mode 100644
index 00000000000..722235f73a2
--- /dev/null
+++ b/cmk/plugins/ibmsvc/rulesets/special_agent.py
@@ -0,0 +1,162 @@
+#!/usr/bin/env python3
+# Copyright (C) 2024 Checkmk GmbH - License: GNU General Public License v2
+# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
+# conditions defined in the file COPYING, which is part of this source code package.
+
+from cmk.rulesets.v1 import Help, Label, Title
+from cmk.rulesets.v1.form_specs import (
+ BooleanChoice,
+ DefaultValue,
+ DictElement,
+ Dictionary,
+ MultipleChoice,
+ MultipleChoiceElement,
+ String,
+ validators,
+)
+from cmk.rulesets.v1.rule_specs import SpecialAgent, Topic
+
+
+def _parameter_form() -> Dictionary:
+ return Dictionary(
+ migrate=_migrate,
+ help_text=Help(
+ "This rule set selects the ibmsvc agent instead of the normal Checkmk Agent "
+ "and allows monitoring of IBM SVC / V7000 storage systems by calling "
+ "ls* commands there over SSH. "
+ "Make sure you have SSH key authentication enabled for your monitoring user. "
+ "That means: The user your monitoring is running under on the monitoring "
+ "system must be able to ssh to the storage system as the user you gave below "
+ "without password."
+ ),
+ elements={
+ "user": DictElement(
+ required=True,
+ parameter_form=String(
+ title=Title("IBM SVC / V7000 user name"),
+ help_text=Help(
+ "User name on the storage system. Read-only permissions are sufficient."
+ ),
+ ),
+ ),
+ "accept_any_hostkey": DictElement(
+ required=True,
+ parameter_form=BooleanChoice(
+ title=Title("Accept any SSH Host Key"),
+ label=Label("Accept any SSH Host Key"),
+ prefill=DefaultValue(False),
+ help_text=Help(
+ "Accepts any SSH Host Key presented by the storage device. "
+ "Please note: This might be a security issue because man-in-the-middle "
+ "attacks are not recognized! Better solution would be to add the "
+ "SSH Host Key of the monitored storage devices to the .ssh/known_hosts "
+ "file for the user your monitoring is running under (on OMD: the site user)"
+ ),
+ ),
+ ),
+ "infos": DictElement(
+ required=True,
+ parameter_form=MultipleChoice(
+ title=Title("Retrieve information about..."),
+ elements=[
+ MultipleChoiceElement(
+ name="lshost",
+ title=Title("Hosts Connected"),
+ ),
+ MultipleChoiceElement(
+ name="lslicense",
+ title=Title("Licensing Status"),
+ ),
+ MultipleChoiceElement(
+ name="lsmdisk",
+ title=Title("MDisks"),
+ ),
+ MultipleChoiceElement(
+ name="lsmdiskgrp",
+ title=Title("MDisksGrps"),
+ ),
+ MultipleChoiceElement(
+ name="lsnode",
+ title=Title("IO Groups"),
+ ),
+ MultipleChoiceElement(
+ name="lsnodestats",
+ title=Title("Node Stats"),
+ ),
+ MultipleChoiceElement(
+ name="lssystem",
+ title=Title("System Info"),
+ ),
+ MultipleChoiceElement(
+ name="lssystemstats",
+ title=Title("System Stats"),
+ ),
+ MultipleChoiceElement(
+ name="lseventlog",
+ title=Title("Event Log"),
+ ),
+ MultipleChoiceElement(
+ name="lsportfc",
+ title=Title("FC Ports"),
+ ),
+ MultipleChoiceElement(
+ name="lsportsas",
+ title=Title("SAS Ports"),
+ ),
+ MultipleChoiceElement(
+ name="lsenclosure",
+ title=Title("Enclosures"),
+ ),
+ MultipleChoiceElement(
+ name="lsenclosurestats",
+ title=Title("Enclosure Stats"),
+ ),
+ MultipleChoiceElement(
+ name="lsarray",
+ title=Title("RAID Arrays"),
+ ),
+ MultipleChoiceElement(
+ name="disks",
+ title=Title("Physical Disks"),
+ ),
+ ],
+ prefill=DefaultValue(
+ [
+ "lshost",
+ "lslicense",
+ "lsmdisk",
+ "lsmdiskgrp",
+ "lsnode",
+ "lsnodestats",
+ "lssystem",
+ "lssystemstats",
+ "lsportfc",
+ "lsenclosure",
+ "lsenclosurestats",
+ "lsarray",
+ "disks",
+ ]
+ ),
+ custom_validate=(validators.LengthInRange(min_value=1),),
+ ),
+ ),
+ },
+ )
+
+
+rule_spec_special_agent_ibmsvc = SpecialAgent(
+ name="ibmsvc",
+ title=Title("IBM SVC / V7000 storage systems"),
+ topic=Topic.STORAGE,
+ parameter_form=_parameter_form,
+)
+
+
+def _migrate(value: object) -> dict[str, object]:
+ if not isinstance(value, dict):
+ raise TypeError(object)
+ if "accept_any_hostkey" in value:
+ return value
+ return {k: v for k, v in value.items() if k != "accept-any-hostkey"} | {
+ "accept_any_hostkey": value["accept-any-hostkey"]
+ }
diff --git a/cmk/plugins/ibmsvc/server_side_calls/special_agent.py b/cmk/plugins/ibmsvc/server_side_calls/special_agent.py
new file mode 100644
index 00000000000..96478c5ae1e
--- /dev/null
+++ b/cmk/plugins/ibmsvc/server_side_calls/special_agent.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+# Copyright (C) 2024 Checkmk GmbH - License: GNU General Public License v2
+# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
+# conditions defined in the file COPYING, which is part of this source code package.
+
+from collections.abc import Iterable, Sequence
+
+from pydantic import BaseModel
+
+from cmk.server_side_calls.v1 import HostConfig, SpecialAgentCommand, SpecialAgentConfig
+
+
+class _Params(BaseModel, frozen=True):
+ user: str
+ accept_any_hostkey: bool
+ infos: Sequence[str]
+
+
+def _commands_function(
+ params: _Params,
+ host_config: HostConfig,
+) -> Iterable[SpecialAgentCommand]:
+ args = ["-u", params.user, "-i", ",".join(params.infos)]
+ if params.accept_any_hostkey:
+ args += ["--accept-any-hostkey"]
+ args.append(host_config.primary_ip_config.address)
+ yield SpecialAgentCommand(command_arguments=args)
+
+
+special_agent_ibmsvc = SpecialAgentConfig(
+ name="ibmsvc",
+ parameter_parser=_Params.model_validate,
+ commands_function=_commands_function,
+)
diff --git a/cmk/utils/password_store/hack.py b/cmk/utils/password_store/hack.py
index 90f5944f09a..47f34996c52 100644
--- a/cmk/utils/password_store/hack.py
+++ b/cmk/utils/password_store/hack.py
@@ -60,6 +60,7 @@
"hivemanager_ng": True,
"hivemanager": True,
"hp_msa": True,
+ "ibmsvc": False, # needs no secret
}
diff --git a/tests/unit/checks/test_agent_ibmsvc.py b/tests/unit/checks/test_agent_ibmsvc.py
deleted file mode 100644
index ce6945ad9dd..00000000000
--- a/tests/unit/checks/test_agent_ibmsvc.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (C) 2019 Checkmk GmbH - License: GNU General Public License v2
-# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
-# conditions defined in the file COPYING, which is part of this source code package.
-
-from collections.abc import Mapping
-
-import pytest
-
-from cmk.base.server_side_calls import SpecialAgentInfoFunctionResult
-
-from .checktestlib import SpecialAgent
-
-pytestmark = pytest.mark.checks
-
-
-@pytest.mark.parametrize(
- "params,expected_args",
- [
- (
- {
- "infos": [
- "lshost",
- "lslicense",
- "lsmdisk",
- "lsmdiskgrp",
- "lsnode",
- "lsnodestats",
- "lssystem",
- "lssystemstats",
- "lsportfc",
- "lsenclosure",
- "lsenclosurestats",
- "lsarray",
- "disks",
- ],
- "user": "user",
- "accept-any-hostkey": True,
- },
- [
- "-u",
- "user",
- "-i",
- "lshost,lslicense,lsmdisk,lsmdiskgrp,lsnode,lsnodestats,lssystem,lssystemstats,lsportfc,lsenclosure,lsenclosurestats,lsarray,disks",
- "--accept-any-hostkey",
- "address",
- ],
- ),
- (
- {
- "infos": [
- "lshost",
- "lslicense",
- "lsmdisk",
- "lsmdiskgrp",
- "lsnode",
- "lsnodestats",
- "lssystem",
- "lssystemstats",
- "lsportfc",
- "lsenclosure",
- "lsenclosurestats",
- "lsarray",
- "disks",
- ],
- "user": "user",
- "accept-any-hostkey": False,
- },
- [
- "-u",
- "user",
- "-i",
- "lshost,lslicense,lsmdisk,lsmdiskgrp,lsnode,lsnodestats,lssystem,lssystemstats,lsportfc,lsenclosure,lsenclosurestats,lsarray,disks",
- "address",
- ],
- ),
- ],
-)
-def test_ibmsvc_argument_parsing(
- params: Mapping[str, object], expected_args: SpecialAgentInfoFunctionResult
-) -> None:
- """Tests if all required arguments are present."""
- agent = SpecialAgent("agent_ibmsvc")
- arguments = agent.argument_func(params, "host", "address")
- assert arguments == expected_args
diff --git a/tests/unit/cmk/plugins/ibmsvc/__init__.py b/tests/unit/cmk/plugins/ibmsvc/__init__.py
new file mode 100644
index 00000000000..c42b91132bf
--- /dev/null
+++ b/tests/unit/cmk/plugins/ibmsvc/__init__.py
@@ -0,0 +1,4 @@
+#!/usr/bin/env python3
+# Copyright (C) 2024 Checkmk GmbH - License: GNU General Public License v2
+# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
+# conditions defined in the file COPYING, which is part of this source code package.
diff --git a/tests/unit/cmk/plugins/ibmsvc/server_side_calls/__init__.py b/tests/unit/cmk/plugins/ibmsvc/server_side_calls/__init__.py
new file mode 100644
index 00000000000..c42b91132bf
--- /dev/null
+++ b/tests/unit/cmk/plugins/ibmsvc/server_side_calls/__init__.py
@@ -0,0 +1,4 @@
+#!/usr/bin/env python3
+# Copyright (C) 2024 Checkmk GmbH - License: GNU General Public License v2
+# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
+# conditions defined in the file COPYING, which is part of this source code package.
diff --git a/tests/unit/cmk/plugins/ibmsvc/server_side_calls/test_special_agent.py b/tests/unit/cmk/plugins/ibmsvc/server_side_calls/test_special_agent.py
new file mode 100644
index 00000000000..e722c584a13
--- /dev/null
+++ b/tests/unit/cmk/plugins/ibmsvc/server_side_calls/test_special_agent.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python3
+# Copyright (C) 2024 Checkmk GmbH - License: GNU General Public License v2
+# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
+# conditions defined in the file COPYING, which is part of this source code package.
+
+from collections.abc import Mapping
+
+import pytest
+
+from cmk.plugins.ibmsvc.server_side_calls.special_agent import special_agent_ibmsvc
+from cmk.server_side_calls.v1 import HostConfig, IPv4Config, SpecialAgentCommand
+
+
+@pytest.mark.parametrize(
+ ["raw_params", "host_config", "expected_result"],
+ [
+ pytest.param(
+ {
+ "user": "user",
+ "accept_any_hostkey": False,
+ "infos": [
+ "lshost",
+ "lslicense",
+ "lsmdisk",
+ ],
+ },
+ HostConfig(
+ name="hostname",
+ ipv4_config=IPv4Config(address="1.2.3.4"),
+ ),
+ SpecialAgentCommand(
+ command_arguments=[
+ "-u",
+ "user",
+ "-i",
+ "lshost,lslicense,lsmdisk",
+ "1.2.3.4",
+ ]
+ ),
+ id="do not accept any host key",
+ ),
+ pytest.param(
+ {
+ "user": "user",
+ "accept_any_hostkey": True,
+ "infos": [
+ "lssystemstats",
+ "lsportfc",
+ "lsenclosure",
+ "lsenclosurestats",
+ "lsarray",
+ ],
+ },
+ HostConfig(
+ name="hostname",
+ ipv4_config=IPv4Config(address="1.2.3.4"),
+ ),
+ SpecialAgentCommand(
+ command_arguments=[
+ "-u",
+ "user",
+ "-i",
+ "lssystemstats,lsportfc,lsenclosure,lsenclosurestats,lsarray",
+ "--accept-any-hostkey",
+ "1.2.3.4",
+ ]
+ ),
+ id="accept any host key",
+ ),
+ ],
+)
+def test_command_creation(
+ raw_params: Mapping[str, object],
+ host_config: HostConfig,
+ expected_result: SpecialAgentCommand,
+) -> None:
+ assert list(
+ special_agent_ibmsvc(
+ raw_params,
+ host_config,
+ )
+ ) == [expected_result]
diff --git a/tests/unit/cmk/plugins_consistency/test_special_agent_args.py b/tests/unit/cmk/plugins_consistency/test_special_agent_args.py
index 5a8ebcc3469..d605c24c2ac 100644
--- a/tests/unit/cmk/plugins_consistency/test_special_agent_args.py
+++ b/tests/unit/cmk/plugins_consistency/test_special_agent_args.py
@@ -103,7 +103,6 @@
}
UNMIGRATED = {
- "ibmsvc",
"innovaphone",
"ipmi_sensors",
"jira",