func resourceVSphereComputeClusterProcessHostUpdate(
	d *schema.ResourceData,
	meta interface{},
	cluster *object.ClusterComputeResource,
) error {
	log.Printf("[DEBUG] %s: Processing any necessary host addition/removal operations", resourceVSphereComputeClusterIDString(d))
	client, err := resourceVSphereComputeClusterClient(meta)
	if err != nil {
		return err
	}

	o, n := d.GetChange("host_system_ids")

	newHosts, err := resourceVSphereComputeClusterGetHostSystemObjects(
		client,
		structure.SliceInterfacesToStrings(n.(*schema.Set).Difference(o.(*schema.Set)).List()),
	)
	if err != nil {
		return err
	}

	oldHosts, err := resourceVSphereComputeClusterGetHostSystemObjects(
		client,
		structure.SliceInterfacesToStrings(o.(*schema.Set).Difference(n.(*schema.Set)).List()),
	)
	if err != nil {
		return err
	}

	// Add new hosts first
	if len(newHosts) > 0 {
		if err := clustercomputeresource.MoveHostsInto(cluster, newHosts); err != nil {
			return fmt.Errorf("error moving new hosts into cluster: %s", err)
		}
	}

	// Remove hosts next
	if err := clustercomputeresource.MoveHostsOutOf(cluster, oldHosts, d.Get("host_cluster_exit_timeout").(int)); err != nil {
		return fmt.Errorf("error moving old hosts out of cluster: %s", err)
	}

	return nil
}
func resourceVSphereComputeClusterProcessHostUpdate(
	d *schema.ResourceData,
	meta interface{},
	cluster *object.ClusterComputeResource,
) error {
	log.Printf("[DEBUG] %s: Processing any necessary host addition/removal operations", resourceVSphereComputeClusterIDString(d))
	client, err := resourceVSphereComputeClusterClient(meta)
	if err != nil {
		return err
	}

	o, n := d.GetChange("host_system_ids")

	newHosts, err := resourceVSphereComputeClusterGetHostSystemObjects(
		client,
		structure.SliceInterfacesToStrings(n.(*schema.Set).Difference(o.(*schema.Set)).List()),
	)
	if err != nil {
		return err
	}

	oldHosts, err := resourceVSphereComputeClusterGetHostSystemObjects(
		client,
		structure.SliceInterfacesToStrings(o.(*schema.Set).Difference(n.(*schema.Set)).List()),
	)
	if err != nil {
		return err
	}

	// Add new hosts first
	if len(newHosts) > 0 {
		if err := clustercomputeresource.MoveHostsInto(cluster, newHosts); err != nil {
			return fmt.Errorf("error moving new hosts into cluster: %s", err)
		}
	}

	// Remove hosts next
	if err := clustercomputeresource.MoveHostsOutOf(cluster, oldHosts, d.Get("host_cluster_exit_timeout").(int)); err != nil {
		return fmt.Errorf("error moving old hosts out of cluster: %s", err)
	}

	return nil
}
// resourceVSphereComputeClusterProcessHostUpdate processes any changes in host
// membership in the cluster.
//
// Note that this has implications for interoperability with any future host
// resources that we may set up in Terraform. This namely exists to support the
// fact that some cluster configuration settings depend on hosts actually
// existing in the cluster before they can be carried out, in addition to the
// fact that we don't have any actual host resources at this point in time, and
// may actually not in the future as the addition of hosts will require
// passwords to be supplied to Terraform, which will propagate to state and
// have security implications.
//
// Currently, this process expects the hosts supplied to host_system_ids to be
// already added to vSphere - the recommended method would be to add these
// hosts OOB as standalone hosts to the datacenter that the cluster is being
// deployed to, and then use the vsphere_host data source to get the necessary
// ID to pass into the vsphere_compute_cluster resource.
//
// Hosts moved *out* of the cluster will be moved to the root host folder of
// the datacenter the cluster belongs to. This will create a ComputeResource MO
// for this host OOB from Terraform. Conversely, moving a host into a cluster
// removes the ComputeResource MO for that host, in addition to moving any VMs
// into the cluster at the root cluster resource pool, removing any resource
// pools that exist on the standalone host.
//
// Hosts being removed are placed into maintenance mode. It is up to the
// operator to determine what the implications of this are - if DRS is set up
// correctly and sufficient resources exist, placing a host into maintenance
// mode *should* migrate powered on VMs off the cluster. Powered off VMs will
// be migrated as well, leaving the host as empty as possible after it leaves
// the cluster. The host will be taken out of maintenance mode after being
// removed.