Source code for saltext.vcf.states.vcf_cluster_config
"""State module for the vSphere 9 cluster Configuration Profile API.
The state below operates at the **cluster** level — the profile applies to
every host in the cluster (vSphere 9 has no per-host imperative REST for
these knobs). Use this to declaratively manage host services, NTP, syslog,
firewall, advanced settings, etc.
Example::
Set NTP servers cluster-wide:
vcf_cluster_config.profile_value:
- name: domain-c9
- key: profile.esx.health.ntp_health.servers
- value:
- pool.ntp.org
- time.cloudflare.com
"""
import requests
from saltext.vcf.clients import cluster_config as c
__virtualname__ = "vcf_cluster_config"
def __virtual__():
return __virtualname__
def _ret(name):
return {"name": name, "changes": {}, "result": True, "comment": ""}
[docs]
def enabled(name, profile=None):
"""Ensure Configuration Profile is enabled on cluster *name*."""
ret = _ret(name)
current = c.enablement_get(__opts__, name, profile=profile) or {}
if current.get("enabled"):
ret["comment"] = f"Configuration Profile already enabled on {name}"
return ret
ret["result"] = False
ret["comment"] = (
f"Configuration Profile not enabled on cluster {name}; enable it via "
"vSphere UI or vLCM tooling before applying this state."
)
return ret
[docs]
def profile_value(name, key, value, profile=None):
"""Ensure a specific Configuration Profile *key* on cluster *name* equals *value*.
*key* is a dotted JSON-Schema-style path (e.g.
``profile.esx.health.ntp_health.servers``). Comparison is exact. When a
change is needed, the state creates a draft, patches just that key, then
applies the draft.
"""
ret = _ret(name)
try:
current_doc = c.configuration_get(__opts__, name, profile=profile)
except requests.HTTPError as exc:
ret["result"] = False
ret["comment"] = f"Could not read cluster {name} configuration: {exc}"
return ret
if current_doc is None:
ret["result"] = False
ret["comment"] = (
f"Cluster {name} has no Configuration Profile yet (not vLCM-managed?). "
"Enable it before applying this state."
)
return ret
current_value = c.get_profile_value(current_doc, key)
if current_value == value:
ret["comment"] = f"{key} on {name} already {value!r}"
return ret
if __opts__["test"]:
ret["result"] = None
ret["comment"] = f"{key} on {name} would change from {current_value!r} to {value!r}"
return ret
draft_id = c.draft_create(__opts__, name, profile=profile)
draft_doc = c.draft_get_configuration(__opts__, name, draft_id, profile=profile)
c.set_profile_value(draft_doc, key, value)
c.draft_update_configuration(__opts__, name, draft_id, draft_doc, profile=profile)
c.draft_apply(__opts__, name, draft_id, profile=profile)
ret["changes"] = {key: {"old": current_value, "new": value}}
ret["comment"] = f"{key} on {name} updated"
return ret