Source code for saltext.vcf.clients.vsan_fault_domain
"""vSAN fault domain configuration (SOAP).
Fault domains group hosts that share a failure boundary (rack, power
domain, blade chassis). vSAN places replica copies across FDs so the
loss of an entire FD doesn't take data offline. Fault domains are
mandatory in stretched-cluster topologies.
Reconfigured via the cluster vSAN reconfig API with a
``vim.cluster.VsanFaultDomainsConfigSpec`` containing a list of
``vim.cluster.VsanFaultDomainSpec`` (name + member hosts).
"""
from pyVmomi import vim
from saltext.vcf.utils import vsan
[docs]
def list_(opts, cluster, profile=None):
"""Return current fault-domain assignments for *cluster*.
Each ESXi host carries its own ``faultDomainInfo`` on
``host.configManager.vsanSystem.config``. VCF 9.x's
``VsanClusterGetConfig`` does not return the per-host array, so we
iterate the cluster's member hosts directly.
Output: a list of ``{"host", "host_id", "fault_domain", "node_uuid"}``
dicts — one per host in the cluster. ``fault_domain`` is None when
the host is not in any FD.
"""
cluster_obj = vsan.find_cluster(opts, cluster, profile=profile)
out = []
for host in cluster_obj.host:
vsan_system = host.configManager.vsanSystem
cfg = vsan_system.config if vsan_system else None
fd_info = getattr(cfg, "faultDomainInfo", None) if cfg else None
cluster_info = getattr(cfg, "clusterInfo", None) if cfg else None
out.append(
{
"host": host.name,
"host_id": host._moId, # noqa: SLF001
"fault_domain": fd_info.name if fd_info and fd_info.name else None,
"node_uuid": cluster_info.nodeUuid if cluster_info else None,
}
)
return out
[docs]
def assign(opts, cluster, mapping, profile=None):
"""Assign hosts to fault domains.
*mapping* is a dict ``{host_id_or_name: fault_domain_name}``. Hosts
referenced by name OR MoId are resolved against the cluster's member
list. Hosts not present in the cluster are silently ignored.
Returns the vim.Task moId.
"""
cluster_obj = vsan.find_cluster(opts, cluster, profile=profile)
cs = vsan.cluster_config_system(opts, profile=profile)
# Group hosts by their target fault-domain name
by_fd: dict[str, list] = {}
for host in cluster_obj.host:
target = mapping.get(host.name) or mapping.get(host._moId) # noqa: SLF001
if target is None:
continue
by_fd.setdefault(target, []).append(host)
fd_specs = []
for fd_name, hosts in by_fd.items():
fd_spec = vim.cluster.VsanFaultDomainSpec()
fd_spec.name = fd_name
fd_spec.hosts = hosts
fd_specs.append(fd_spec)
fds_config = vim.cluster.VsanFaultDomainsConfigSpec()
fds_config.faultDomains = fd_specs
spec = vim.vsan.ReconfigSpec()
spec.faultDomainsSpec = fds_config
task = cs.VsanClusterReconfig(cluster=cluster_obj, vsanReconfigSpec=spec)
return task._moId # noqa: SLF001