vsphere/internal/helper/storagepod/storage_pod_helper.go
func CreateVM(
	client *govmomi.Client,
	fo *object.Folder,
	spec types.VirtualMachineConfigSpec,
	pool *object.ResourcePool,
	host *object.HostSystem,
	pod *object.StoragePod,
) (*object.VirtualMachine, error) {
	sdrsEnabled, err := StorageDRSEnabled(pod)
	if err != nil {
		return nil, err
	}
	if !sdrsEnabled {
		return nil, fmt.Errorf("storage DRS is not enabled on datastore cluster %q", pod.Name())
	}
	log.Printf(
		"[DEBUG] Creating virtual machine %q on datastore cluster %q",
		fmt.Sprintf("%s/%s", fo.InventoryPath, spec.Name),
		pod.Name(),
	)
	sps := types.StoragePlacementSpec{
		Type:         string(types.StoragePlacementSpecPlacementTypeCreate),
		ResourcePool: types.NewReference(pool.Reference()),
		PodSelectionSpec: types.StorageDrsPodSelectionSpec{
			StoragePod:      types.NewReference(pod.Reference()),
			InitialVmConfig: expandVMPodConfigForPlacement(spec.DeviceChange, pod),
		},
		ConfigSpec: &spec,
		Folder:     types.NewReference(fo.Reference()),
	}
	if host != nil {
		sps.Host = types.NewReference(host.Reference())
	}

	placement, err := recommendSDRS(client, sps, provider.DefaultAPITimeout)
	if err != nil {
		return nil, err
	}
	// If the parent resource pool is a vApp, we need to create the VM using the
	// CreateChildVM vApp function instead of directly using SDRS recommendations.
	if sps.ResourcePool != nil {
		vc, err := vappcontainer.FromID(client, sps.ResourcePool.Reference().Value)
		switch {
		case viapi.IsManagedObjectNotFoundError(err):
			// This isn't a vApp container, so continue with normal SDRS work flow.
		case err == nil:
			return createVAppVMFromSPS(client, placement, spec, sps, vc)
		default:
			return nil, err
		}
	}
	return applySDRS(client, placement, provider.DefaultAPITimeout)
}
func CreateVM(
	client *govmomi.Client,
	fo *object.Folder,
	spec types.VirtualMachineConfigSpec,
	pool *object.ResourcePool,
	host *object.HostSystem,
	pod *object.StoragePod,
) (*object.VirtualMachine, error) {
	sdrsEnabled, err := StorageDRSEnabled(pod)
	if err != nil {
		return nil, err
	}
	if !sdrsEnabled {
		return nil, fmt.Errorf("storage DRS is not enabled on datastore cluster %q", pod.Name())
	}
	log.Printf(
		"[DEBUG] Creating virtual machine %q on datastore cluster %q",
		fmt.Sprintf("%s/%s", fo.InventoryPath, spec.Name),
		pod.Name(),
	)
	sps := types.StoragePlacementSpec{
		Type:         string(types.StoragePlacementSpecPlacementTypeCreate),
		ResourcePool: types.NewReference(pool.Reference()),
		PodSelectionSpec: types.StorageDrsPodSelectionSpec{
			StoragePod:      types.NewReference(pod.Reference()),
			InitialVmConfig: expandVMPodConfigForPlacement(spec.DeviceChange, pod),
		},
		ConfigSpec: &spec,
		Folder:     types.NewReference(fo.Reference()),
	}
	if host != nil {
		sps.Host = types.NewReference(host.Reference())
	}

	placement, err := recommendSDRS(client, sps, provider.DefaultAPITimeout)
	if err != nil {
		return nil, err
	}
	// If the parent resource pool is a vApp, we need to create the VM using the
	// CreateChildVM vApp function instead of directly using SDRS recommendations.
	if sps.ResourcePool != nil {
		vc, err := vappcontainer.FromID(client, sps.ResourcePool.Reference().Value)
		switch {
		case viapi.IsManagedObjectNotFoundError(err):
			// This isn't a vApp container, so continue with normal SDRS work flow.
		case err == nil:
			return createVAppVMFromSPS(client, placement, spec, sps, vc)
		default:
			return nil, err
		}
	}
	return applySDRS(client, placement, provider.DefaultAPITimeout)
}
// CreateVM creates a virtual machine on a datastore cluster via the
// StorageResourceManager API. It mimics our helper in the virtualmachine
// package in functionality, returning a VM helper object on success.