Skip to content

Commit

Permalink
16876 FIX Nutanix agent: resolve verify error when environment REQUES…
Browse files Browse the repository at this point in the history
…T_CA_BUNDLE is set

Due to a specific behaviour in the requests Python library, the SSL verify disable
option does not work when the REQUEST_CA_BUNDLE environment variable is set. This
also affected the Nutanix agent. This werk resolves the error and therefore always
respects the no-cert-check flag. In addition, this werk also improves the error
message in case the agent fails when requesting the Nutanix API.

closes PR-703
CMK-17734

Change-Id: I04ddf2534f8104d144a99bbaf5940de5524f166f
  • Loading branch information
anthonyh209 committed Jun 9, 2024
1 parent 1cf07e9 commit 02a54dd
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 43 deletions.
18 changes: 18 additions & 0 deletions .werks/16876.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[//]: # (werk v2)
# Nutanix agent: resolve verify error when environment REQUEST_CA_BUNDLE is set

key | value
---------- | ---
date | 2024-06-08T22:17:32+00:00
version | 2.4.0b1
class | fix
edition | cee
component | checks
level | 1
compatible | yes

Due to a specific behaviour in the requests Python library, the SSL verify disable
option does not work when the REQUEST_CA_BUNDLE environment variable is set. This
also affected the Nutanix agent. This werk resolves the error and therefore always
respects the no-cert-check flag. In addition, this werk also improves the error
message in case the agent fails when requesting the Nutanix API.
98 changes: 55 additions & 43 deletions cmk/special_agents/agent_prism.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import logging
import sys
from collections.abc import Sequence
from typing import Any

import requests

Expand All @@ -19,6 +20,24 @@
LOGGING = logging.getLogger("agent_prism")


class SessionManager:
def __init__(
self, username: str, password: str, timeout: int, no_cert_check: bool = False
) -> None:
self._session = requests.Session()
auth_encoded = base64.b64encode(f"{username}:{password}".encode()).decode()
self._session.headers.update({"Authorization": f"Basic {auth_encoded}"})
self._verify = (
False if no_cert_check else True # pylint: disable=simplifiable-if-expression
)
self._timeout = timeout

def get(self, url: str, params: dict[str, str] | None = None) -> Any:
resp = self._session.get(url, params=params, verify=self._verify, timeout=self._timeout)
resp.raise_for_status()
return resp.json()


def parse_arguments(argv: Sequence[str] | None) -> Args:
parser = create_default_argument_parser(description=__doc__)
parser.add_argument(
Expand All @@ -44,81 +63,78 @@ def parse_arguments(argv: Sequence[str] | None) -> Args:
return parser.parse_args(argv)


def output_containers(session: requests.Session, url: str, timeout: int) -> None:
def output_containers(session_manager: SessionManager, url: str) -> None:
LOGGING.debug("do request..")
obj = session.get(url + "/containers", timeout=timeout).json()
obj = session_manager.get(url + "/containers")
LOGGING.debug("got %d containers", len(obj["entities"]))
with SectionWriter("prism_containers") as w:
w.append_json(obj)


def output_alerts(session: requests.Session, url: str, timeout: int) -> None:
def output_alerts(session_manager: SessionManager, url: str) -> None:
LOGGING.debug("do request..")
obj = session.get(
obj = session_manager.get(
url + "/alerts",
params={"resolved": "false", "acknowledged": "false"},
timeout=timeout,
).json()
)
LOGGING.debug("got %d alerts", len(obj["entities"]))
with SectionWriter("prism_alerts") as w:
w.append_json(obj)


def output_cluster(session: requests.Session, url: str, timeout: int) -> None:
def output_cluster(session_manager: SessionManager, url: str) -> None:
LOGGING.debug("do request..")
obj = session.get(url + "/cluster", timeout=timeout).json()
obj = session_manager.get(url + "/cluster")
LOGGING.debug("got %d keys", len(obj.keys()))
with SectionWriter("prism_info") as w:
w.append_json(obj)


def output_storage_pools(session: requests.Session, url: str, timeout: int) -> None:
def output_storage_pools(session_manager: SessionManager, url: str) -> None:
LOGGING.debug("do request..")
obj = session.get(url + "/storage_pools", timeout=timeout).json()
obj = session_manager.get(url + "/storage_pools")
LOGGING.debug("got %d entities", len(obj["entities"]))
with SectionWriter("prism_storage_pools") as w:
w.append_json(obj)


def output_vms(session: requests.Session, url: str, timeout: int) -> None:
obj = session.get(url + "/vms", timeout=timeout).json()
def output_vms(session_manager: SessionManager, url: str) -> None:
obj = session_manager.get(url + "/vms")
with SectionWriter("prism_vms") as w:
w.append_json(obj)
for element in obj.get("entities"):
for element in obj.get("entities", []):
with ConditionalPiggybackSection(element.get("vmName")):
with SectionWriter("prism_vm") as w:
w.append_json(element)


def output_hosts(session: requests.Session, url: str, timeout: int) -> None:
obj = session.get(url + "/hosts", timeout=timeout).json()
def output_hosts(session_manager: SessionManager, url: str) -> None:
obj = session_manager.get(url + "/hosts")
with SectionWriter("prism_hosts") as w:
w.append_json(obj)
for element in obj.get("entities"):
for element in obj.get("entities", []):
with ConditionalPiggybackSection(element.get("name")):
with SectionWriter("prism_host") as w:
w.append_json(element)
networks = session.get(
url + f"/hosts/{element.get("uuid")}/host_nics", timeout=timeout
).json()
networks = session_manager.get(url + f"/hosts/{element.get("uuid")}/host_nics")
with SectionWriter("prism_host_networks") as w:
w.append_json(networks)


def output_protection(session: requests.Session, url: str, timeout: int) -> None:
obj = session.get(url + "/protection_domains", timeout=timeout).json()
def output_protection(session_manager: SessionManager, url: str) -> None:
obj = session_manager.get(url + "/protection_domains")
with SectionWriter("prism_protection_domains") as w:
w.append_json(obj)


def output_support(session: requests.Session, url: str, timeout: int) -> None:
obj = session.get(url + "/cluster/remote_support", timeout=timeout).json()
def output_support(session_manager: SessionManager, url: str) -> None:
obj = session_manager.get(url + "/cluster/remote_support")
with SectionWriter("prism_remote_support") as w:
w.append_json(obj)


def output_ha(session: requests.Session, url: str, timeout: int) -> None:
obj = session.get(url + "/ha", timeout=timeout).json()
def output_ha(session_manager: SessionManager, url: str) -> None:
obj = session_manager.get(url + "/ha")
with SectionWriter("prism_ha") as w:
w.append_json(obj)

Expand All @@ -129,43 +145,39 @@ def agent_prism_main(args: Args) -> int:
LOGGING.info("setup HTTPS connection..")
base_url_v1 = f"https://{args.server}:{args.port}/PrismGateway/services/rest/v1"
base_url_v2 = f"https://{args.server}:{args.port}/PrismGateway/services/rest/v2.0"
session = requests.session()
session.headers.update(
{
"Authorization": "Basic "
+ base64.b64encode(f"{args.username}:{args.password}".encode()).decode()
}
)
session.verify = (
False if args.no_cert_check else True # pylint: disable=simplifiable-if-expression
session_manager = SessionManager(
username=args.username,
password=args.password,
timeout=args.timeout,
no_cert_check=args.no_cert_check,
)

LOGGING.info("fetch and write container info..")
output_containers(session, base_url_v1, timeout=args.timeout)
output_containers(session_manager, base_url_v1)

LOGGING.info("fetch and write alerts..")
output_alerts(session, base_url_v2, timeout=args.timeout)
output_alerts(session_manager, base_url_v2)

LOGGING.info("fetch and write cluster info..")
output_cluster(session, base_url_v2, timeout=args.timeout)
output_cluster(session_manager, base_url_v2)

LOGGING.info("fetch and write storage_pools..")
output_storage_pools(session, base_url_v1, timeout=args.timeout)
output_storage_pools(session_manager, base_url_v1)

LOGGING.info("fetch and write vm info..")
output_vms(session, base_url_v1, timeout=args.timeout)
output_vms(session_manager, base_url_v1)

LOGGING.info("fetch and write hosts info..")
output_hosts(session, base_url_v2, timeout=args.timeout)
output_hosts(session_manager, base_url_v2)

LOGGING.info("fetch and write protection domain info..")
output_protection(session, base_url_v2, timeout=args.timeout)
output_protection(session_manager, base_url_v2)

LOGGING.info("fetch and write support info..")
output_support(session, base_url_v2, timeout=args.timeout)
output_support(session_manager, base_url_v2)

LOGGING.info("fetch and write ha state..")
output_ha(session, base_url_v2, timeout=args.timeout)
output_ha(session_manager, base_url_v2)

LOGGING.info("all done. bye.")

Expand Down

0 comments on commit 02a54dd

Please sign in to comment.