vsphere/internal/vmworkflow/virtual_machine_clone_subresource.go
func ValidateVirtualMachineClone(d *schema.ResourceDiff, c *govmomi.Client) error {
	tUUID := d.Get("clone.0.template_uuid").(string)
	log.Printf("[DEBUG] ValidateVirtualMachineClone: Validating fitness of source VM/template %s", tUUID)
	vm, err := virtualmachine.FromUUID(c, tUUID)
	if err != nil {
		return fmt.Errorf("cannot locate virtual machine or template with UUID %q: %s", tUUID, err)
	}
	vprops, err := virtualmachine.Properties(vm)
	if err != nil {
		return fmt.Errorf("error fetching virtual machine or template properties: %s", err)
	}
	// The virtual machine needs to be powered off to be suitable for cloning.
	if vprops.Runtime.PowerState != types.VirtualMachinePowerStatePoweredOff {
		return fmt.Errorf("virtual machine %s must be powered off to be used as a source for cloning", tUUID)
	}
	// Check to see if our guest IDs match.
	eGuestID := vprops.Config.GuestId
	aGuestID := d.Get("guest_id").(string)
	if eGuestID != aGuestID {
		return fmt.Errorf("invalid guest ID %q for clone. Please set it to %q", aGuestID, eGuestID)
	}
	// If linked clone is enabled, check to see if we have a snapshot. There need
	// to be a single snapshot on the template for it to be eligible.
	linked := d.Get("clone.0.linked_clone").(bool)
	if linked {
		log.Printf("[DEBUG] ValidateVirtualMachineClone: Checking snapshots on %s for linked clone eligibility", tUUID)
		if err := validateCloneSnapshots(vprops); err != nil {
			return err
		}
	}
	// Check to make sure the disks for this VM/template line up with the disks
	// in the configuration. This is in the virtual device package, so pass off
	// to that now.
	l := object.VirtualDeviceList(vprops.Config.Hardware.Device)
	if err := virtualdevice.DiskCloneValidateOperation(d, c, l, linked); err != nil {
		return err
	}

	// If a customization spec was defined, we need to check some items in it as well.
	if len(d.Get("clone.0.customize").([]interface{})) > 0 {
		if poolID, ok := d.GetOk("resource_pool_id"); ok {
			pool, err := resourcepool.FromID(c, poolID.(string))
			if err != nil {
				return fmt.Errorf("could not find resource pool ID %q: %s", poolID, err)
			}
			family, err := resourcepool.OSFamily(c, pool, d.Get("guest_id").(string))
			if err != nil {
				return fmt.Errorf("cannot find OS family for guest ID %q: %s", d.Get("guest_id").(string), err)
			}
			if err := ValidateCustomizationSpec(d, family); err != nil {
				return err
			}
		} else {
			log.Printf("[DEBUG] ValidateVirtualMachineClone: resource_pool_id is not available. Skipping OS family check.")
		}
	}
	vconfig := vprops.Config.VAppConfig
	if vconfig != nil {
		// We need to set the vApp transport types here so that it is available
		// later in CustomizeDiff where transport requirements are validated in
		// ValidateVAppTransport
		d.SetNew("vapp_transport", vconfig.GetVmConfigInfo().OvfEnvironmentTransport)
	}

	log.Printf("[DEBUG] ValidateVirtualMachineClone: Source VM/template %s is a suitable source for cloning", tUUID)
	return nil
}
func ValidateVirtualMachineClone(d *schema.ResourceDiff, c *govmomi.Client) error {
	tUUID := d.Get("clone.0.template_uuid").(string)
	log.Printf("[DEBUG] ValidateVirtualMachineClone: Validating fitness of source VM/template %s", tUUID)
	vm, err := virtualmachine.FromUUID(c, tUUID)
	if err != nil {
		return fmt.Errorf("cannot locate virtual machine or template with UUID %q: %s", tUUID, err)
	}
	vprops, err := virtualmachine.Properties(vm)
	if err != nil {
		return fmt.Errorf("error fetching virtual machine or template properties: %s", err)
	}
	// The virtual machine needs to be powered off to be suitable for cloning.
	if vprops.Runtime.PowerState != types.VirtualMachinePowerStatePoweredOff {
		return fmt.Errorf("virtual machine %s must be powered off to be used as a source for cloning", tUUID)
	}
	// Check to see if our guest IDs match.
	eGuestID := vprops.Config.GuestId
	aGuestID := d.Get("guest_id").(string)
	if eGuestID != aGuestID {
		return fmt.Errorf("invalid guest ID %q for clone. Please set it to %q", aGuestID, eGuestID)
	}
	// If linked clone is enabled, check to see if we have a snapshot. There need
	// to be a single snapshot on the template for it to be eligible.
	linked := d.Get("clone.0.linked_clone").(bool)
	if linked {
		log.Printf("[DEBUG] ValidateVirtualMachineClone: Checking snapshots on %s for linked clone eligibility", tUUID)
		if err := validateCloneSnapshots(vprops); err != nil {
			return err
		}
	}
	// Check to make sure the disks for this VM/template line up with the disks
	// in the configuration. This is in the virtual device package, so pass off
	// to that now.
	l := object.VirtualDeviceList(vprops.Config.Hardware.Device)
	if err := virtualdevice.DiskCloneValidateOperation(d, c, l, linked); err != nil {
		return err
	}

	// If a customization spec was defined, we need to check some items in it as well.
	if len(d.Get("clone.0.customize").([]interface{})) > 0 {
		if poolID, ok := d.GetOk("resource_pool_id"); ok {
			pool, err := resourcepool.FromID(c, poolID.(string))
			if err != nil {
				return fmt.Errorf("could not find resource pool ID %q: %s", poolID, err)
			}
			family, err := resourcepool.OSFamily(c, pool, d.Get("guest_id").(string))
			if err != nil {
				return fmt.Errorf("cannot find OS family for guest ID %q: %s", d.Get("guest_id").(string), err)
			}
			if err := ValidateCustomizationSpec(d, family); err != nil {
				return err
			}
		} else {
			log.Printf("[DEBUG] ValidateVirtualMachineClone: resource_pool_id is not available. Skipping OS family check.")
		}
	}
	vconfig := vprops.Config.VAppConfig
	if vconfig != nil {
		// We need to set the vApp transport types here so that it is available
		// later in CustomizeDiff where transport requirements are validated in
		// ValidateVAppTransport
		d.SetNew("vapp_transport", vconfig.GetVmConfigInfo().OvfEnvironmentTransport)
	}

	log.Printf("[DEBUG] ValidateVirtualMachineClone: Source VM/template %s is a suitable source for cloning", tUUID)
	return nil
}
func ValidateVirtualMachineClone ( d * schema . ResourceDiff , c * govmomi . Client ) error { tUUID := d . Get ( " " ) . ( string ) log . Printf ( " " , tUUID ) vm , err := virtualmachine . FromUUID ( c , tUUID ) if err != nil { return fmt . Errorf ( " " , tUUID , err ) } vprops , err := virtualmachine . Properties ( vm ) if err != nil { return fmt . Errorf ( " " , err ) } // The virtual machine needs to be powered off to be suitable for cloning. if vprops . Runtime . PowerState != types . VirtualMachinePowerStatePoweredOff { return fmt . Errorf ( " " , tUUID ) } // Check to see if our guest IDs match. eGuestID := vprops . Config . GuestId aGuestID := d . Get ( " " ) . ( string ) if eGuestID != aGuestID { return fmt . Errorf ( " " , aGuestID , eGuestID ) } // If linked clone is enabled, check to see if we have a snapshot. There need // to be a single snapshot on the template for it to be eligible. linked := d . Get ( " " ) . ( bool ) if linked { log . Printf ( " " , tUUID ) if err := validateCloneSnapshots ( vprops ) ; err != nil { return err } } // Check to make sure the disks for this VM/template line up with the disks // in the configuration. This is in the virtual device package, so pass off // to that now. l := object . VirtualDeviceList ( vprops . Config . Hardware . Device ) if err := virtualdevice . DiskCloneValidateOperation ( d , c , l , linked ) ; err != nil { return err } // If a customization spec was defined, we need to check some items in it as well. if len ( d . Get ( " " ) . ( [ ] interface { } ) ) > 0 { if poolID , ok := d . GetOk ( " " ) ; ok { pool , err := resourcepool . FromID ( c , poolID . ( string ) ) if err != nil { return fmt . Errorf ( " " , poolID , err ) } family , err := resourcepool . OSFamily ( c , pool , d . Get ( " " ) . ( string ) ) if err != nil { return fmt . Errorf ( " " , d . Get ( " " ) . ( string ) , err ) } if err := ValidateCustomizationSpec ( d , family ) ; err != nil { return err } } else { log . Printf ( " " ) } } vconfig := vprops . Config . VAppConfig if vconfig != nil { // We need to set the vApp transport types here so that it is available // later in CustomizeDiff where transport requirements are validated in // ValidateVAppTransport d . SetNew ( " " , vconfig . GetVmConfigInfo ( ) . OvfEnvironmentTransport ) } log . Printf ( " " , tUUID ) return nil }
// ValidateVirtualMachineClone does pre-creation validation of a virtual
// machine's configuration to make sure it's suitable for use in cloning.
// This includes, but is not limited to checking to make sure that the disks in
// the new VM configuration line up with the configuration in the existing
// template, and checking to make sure that the VM has a single snapshot we can
// use in the even that linked clones are enabled.
ValidateVirtualMachineClone does pre - creation validation of a virtual machine s configuration to make sure it s suitable for use in cloning . This includes but is not limited to checking to make sure that the disks in the new VM configuration line up with the configuration in the existing template and checking to make sure that the VM has a single snapshot we can use in the even that linked clones are enabled .