// CreateVM creates a new virtual machine
CreateVM creates a new virtual machine
// CreateVM creates a new virtual machine
func (m *Manager) CreateVM(name string, memoryMB int64, cpus int, limitCPUFeatures bool, notes []string, generation GenerationType, secureBoot bool) (*VirtualMachine, error) {
	vmSettingsDataInstance, err := m.con.Get(VirtualSystemSettingDataClass)
	if err != nil {
		return nil, err
	}
	newVMInstance, err := vmSettingsDataInstance.Get("SpawnInstance_")
	if err != nil {
		return nil, errors.Wrap(err, "calling SpawnInstance_")
	}
	if err := newVMInstance.Set("ElementName", name); err != nil {
		return nil, errors.Wrap(err, "Set ElementName")
	}
	if err := newVMInstance.Set("VirtualSystemSubType", string(generation)); err != nil {
		return nil, errors.Wrap(err, "Set VirtualSystemSubType")
	}
	if generation == Generation2 {
		if err := newVMInstance.Set("SecureBootEnabled", secureBoot); err != nil {
			return nil, errors.Wrap(err, "Set VirtualSystemSubType")
		}
	}
	if notes != nil && len(notes) > 0 {
		vmNotes := []string{strings.Join(notes, "\n")}
		if err := newVMInstance.Set("Notes", vmNotes); err != nil {
			return nil, errors.Wrap(err, "Set Notes")
		}
	}
	vmText, err := newVMInstance.GetText(1)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to get VM instance XML")
	}
	jobPath := ole.VARIANT{}
	resultingSystem := ole.VARIANT{}
	jobState, err := m.svc.Get("DefineSystem", vmText, nil, nil, &resultingSystem, &jobPath)
	if err != nil {
		return nil, errors.Wrap(err, "calling DefineSystem")
	}
	if jobState.Value().(int32) == wmi.JobStatusStarted {
		err := wmi.WaitForJob(jobPath.Value().(string))
		if err != nil {
			return nil, errors.Wrap(err, "waiting for job")
		}
	}
	locationURI := resultingSystem.Value().(string)
	loc, err := wmi.NewLocation(locationURI)
	if err != nil {
		return nil, errors.Wrap(err, "getting location")
	}
	result, err := loc.GetResult()
	if err != nil {
		return nil, errors.Wrap(err, "getting result")
	}
	id, err := result.GetProperty("Name")
	if err != nil {
		return nil, errors.Wrap(err, "fetching VM ID")
	}
	vm, err := m.GetVM(id.Value().(string))
	if err != nil {
		return nil, errors.Wrap(err, "fetching VM")
	}
	if err := vm.SetMemory(memoryMB); err != nil {
		return nil, errors.Wrap(err, "setting memory limit")
	}
	if err := vm.SetCPUs(cpus, limitCPUFeatures); err != nil {
		return nil, errors.Wrap(err, "setting CPU limit")
	}
	bootOrder := []int32{
		int32(BootHDD),
		int32(BootPXE),
		int32(BootCDROM),
		int32(BootFloppy),
	}
	if err := vm.SetBootOrder(bootOrder); err != nil {
		return nil, errors.Wrap(err, "setting boot order")
	}
	return vm, nil
}
func ( m * Manager ) CreateVM ( name string , memoryMB int64 , cpus int , limitCPUFeatures bool , notes [ ] string , generation GenerationType , secureBoot bool ) ( * VirtualMachine , error ) { vmSettingsDataInstance , err := m . con . Get ( VirtualSystemSettingDataClass ) if err != nil { return nil , err } newVMInstance , err := vmSettingsDataInstance . Get ( " " ) if err != nil { return nil , errors . Wrap ( err , " " ) } if err := newVMInstance . Set ( " " , name ) ; err != nil { return nil , errors . Wrap ( err , " " ) } if err := newVMInstance . Set ( " " , string ( generation ) ) ; err != nil { return nil , errors . Wrap ( err , " " ) } if generation == Generation2 { if err := newVMInstance . Set ( " " , secureBoot ) ; err != nil { return nil , errors . Wrap ( err , " " ) } } if notes != nil && len ( notes ) > 0 { vmNotes := [ ] string { strings . Join ( notes , " \n " ) } if err := newVMInstance . Set ( " " , vmNotes ) ; err != nil { return nil , errors . Wrap ( err , " " ) } } vmText , err := newVMInstance . GetText ( 1 ) if err != nil { return nil , errors . Wrap ( err , " " ) } jobPath := ole . VARIANT { } resultingSystem := ole . VARIANT { } jobState , err := m . svc . Get ( " " , vmText , nil , nil , & resultingSystem , & jobPath ) if err != nil { return nil , errors . Wrap ( err , " " ) } if jobState . Value ( ) . ( int32 ) == wmi . JobStatusStarted { err := wmi . WaitForJob ( jobPath . Value ( ) . ( string ) ) if err != nil { return nil , errors . Wrap ( err , " " ) } } locationURI := resultingSystem . Value ( ) . ( string ) loc , err := wmi . NewLocation ( locationURI ) if err != nil { return nil , errors . Wrap ( err , " " ) } result , err := loc . GetResult ( ) if err != nil { return nil , errors . Wrap ( err , " " ) } id , err := result . GetProperty ( " " ) if err != nil { return nil , errors . Wrap ( err , " " ) } vm , err := m . GetVM ( id . Value ( ) . ( string ) ) if err != nil { return nil , errors . Wrap ( err , " " ) } if err := vm . SetMemory ( memoryMB ) ; err != nil { return nil , errors . Wrap ( err , " " ) } if err := vm . SetCPUs ( cpus , limitCPUFeatures ) ; err != nil { return nil , errors . Wrap ( err , " " ) } bootOrder := [ ] int32 { int32 ( BootHDD ) , int32 ( BootPXE ) , int32 ( BootCDROM ) , int32 ( BootFloppy ) , } if err := vm . SetBootOrder ( bootOrder ) ; err != nil { return nil , errors . Wrap ( err , " " ) } return vm , nil }
CreateVM creates a new virtual machine
CreateVM creates a new virtual machine
// Don't ask... // Well, ok...if you must. The Msvm_VirtualSystemSettingData has a Notes // property of type []string. But in reality, it only cares about the first // element of that array. So we join the notes into one newline delimited // string, and set that as the first and only element in a new []string{} // The resultingSystem value for DefineSystem is always a string containing the // location of the newly created resource // The name field of the returning class is actually the InstanceID...