// Init initializes the VirtualBox global data structures. // // Due to VirtualBox oddness, Init should ideally be called in the // application's main thread. The odds of this happening are maximized by // calling Init() from the application's main goroutine. // // It returns any error encountered. func Init() error { // For convenience, Init() is idempotent. if glueInitialized == false { result := C.GoVboxCGlueInit() if C.GoVboxFAILED(result) != 0 { cmessage := C.GoString(&C.g_szVBoxErrMsg[0]) return errors.New(fmt.Sprintf("VBoxCGlueInit failed: %s", cmessage)) } glueInitialized = true AppVersion = uint(C.GoVboxGetAppVersion()) ApiVersion = uint(C.GoVboxGetApiVersion()) } if client == nil { result := C.GoVboxClientInitialize(&client) if C.GoVboxFAILED(result) != 0 || client == nil { client = nil return errors.New(fmt.Sprintf("pfnClientInitialize failed: %x", result)) } } if cbox == nil { result := C.GoVboxGetVirtualBox(client, &cbox) if C.GoVboxFAILED(result) != 0 || cbox == nil { cbox = nil return errors.New(fmt.Sprintf("Failed to get IVirtualBox: %x", result)) } } return nil }
// GetMediumFormats returns the guest OS formats supported by VirtualBox. // It returns a slice of MediumFormat instances and any error encountered. func (props *SystemProperties) GetMediumFormats() ([]MediumFormat, error) { var cformatsPtr **C.IMediumFormat var formatCount C.ULONG result := C.GoVboxGetMediumFormats(props.cprops, &cformatsPtr, &formatCount) if C.GoVboxFAILED(result) != 0 || (cformatsPtr == nil && formatCount > 0) { return nil, errors.New( fmt.Sprintf("Failed to get IMediumFormat array: %x", result)) } sliceHeader := reflect.SliceHeader{ Data: uintptr(unsafe.Pointer(cformatsPtr)), Len: int(formatCount), Cap: int(formatCount), } cformatsSlice := *(*[]*C.IMediumFormat)(unsafe.Pointer(&sliceHeader)) var formats = make([]MediumFormat, formatCount) for i := range cformatsSlice { formats[i] = MediumFormat{cformatsSlice[i]} } C.GoVboxArrayOutFree(unsafe.Pointer(cformatsPtr)) return formats, nil }
// Unregister removes this from VirtualBox's list of registered machines. // The returned slice of Medium instances is intended to be passed to // DeleteConfig to get all the VM's files cleaned. // It returns an array of detached Medium instances and any error encountered. func (machine *Machine) Unregister(cleanupMode CleanupMode) ([]Medium, error) { var cmediaPtr **C.IMedium var mediaCount C.ULONG result := C.GoVboxMachineUnregister(machine.cmachine, C.PRUint32(cleanupMode), &cmediaPtr, &mediaCount) if C.GoVboxFAILED(result) != 0 || (cmediaPtr == nil && mediaCount != 0) { return nil, errors.New( fmt.Sprintf("Failed to unregister IMachine: %x", result)) } sliceHeader := reflect.SliceHeader{ Data: uintptr(unsafe.Pointer(cmediaPtr)), Len: int(mediaCount), Cap: int(mediaCount), } cmediaSlice := *(*[]*C.IMedium)(unsafe.Pointer(&sliceHeader)) var media = make([]Medium, mediaCount) for i := range cmediaSlice { media[i] = Medium{cmediaSlice[i]} } C.GoVboxArrayOutFree(unsafe.Pointer(cmediaPtr)) return media, nil }
// GetMachines returns the machines known to VirtualBox. // It returns a slice of Machine instances and any error encountered. func GetMachines() ([]Machine, error) { if err := Init(); err != nil { return nil, err } var cmachinesPtr **C.IMachine var machineCount C.ULONG result := C.GoVboxGetMachines(cbox, &cmachinesPtr, &machineCount) if C.GoVboxFAILED(result) != 0 || (cmachinesPtr == nil && machineCount != 0) { return nil, errors.New( fmt.Sprintf("Failed to get IMachine array: %x", result)) } sliceHeader := reflect.SliceHeader{ Data: uintptr(unsafe.Pointer(cmachinesPtr)), Len: int(machineCount), Cap: int(machineCount), } cmachinesSlice := *(*[]*C.IMachine)(unsafe.Pointer(&sliceHeader)) var machines = make([]Machine, machineCount) for i := range cmachinesSlice { machines[i] = Machine{cmachinesSlice[i]} } C.GoVboxArrayOutFree(unsafe.Pointer(cmachinesPtr)) return machines, nil }
// ComposeMachineFilename returns a default VM config file path. // If baseFolder is empty, VirtualBox's default machine folder will be used. // It returns a string and any error encountered. func ComposeMachineFilename( name string, flags string, baseFolder string) (string, error) { if err := Init(); err != nil { return "", err } var cpath *C.char cname := C.CString(name) cflags := C.CString(flags) cbaseFolder := C.CString(baseFolder) result := C.GoVboxComposeMachineFilename(cbox, cname, cflags, cbaseFolder, &cpath) C.free(unsafe.Pointer(cname)) C.free(unsafe.Pointer(cflags)) C.free(unsafe.Pointer(cbaseFolder)) if C.GoVboxFAILED(result) != 0 || cpath == nil { return "", errors.New( fmt.Sprintf("IVirtualBox failed to compose machine name: %x", result)) } path := C.GoString(cpath) C.GoVboxUtf8Free(cpath) return path, nil }
// GetGuestOsTypes returns the guest OS types supported by VirtualBox. // It returns a slice of GuestOsType instances and any error encountered. func GetGuestOsTypes() ([]GuestOsType, error) { if err := Init(); err != nil { return nil, err } var ctypesPtr **C.IGuestOSType var typeCount C.ULONG result := C.GoVboxGetGuestOSTypes(cbox, &ctypesPtr, &typeCount) if C.GoVboxFAILED(result) != 0 || (ctypesPtr == nil && typeCount != 0) { return nil, errors.New( fmt.Sprintf("Failed to get IGuestOSType array: %x", result)) } sliceHeader := reflect.SliceHeader{ Data: uintptr(unsafe.Pointer(ctypesPtr)), Len: int(typeCount), Cap: int(typeCount), } ctypesSlice := *(*[]*C.IGuestOSType)(unsafe.Pointer(&sliceHeader)) var types = make([]GuestOsType, typeCount) for i := range ctypesSlice { types[i] = GuestOsType{ctypesSlice[i]} } C.GoVboxArrayOutFree(unsafe.Pointer(ctypesPtr)) return types, nil }
// Close removes the bond between the Medium object and the image backing it. // After this call, the Medium instance should be released, as any calls // involving it will error out. The image file is not deleted, so it can be // bound to a new Medium by calling OpenMedium. // It returns any error encountered. func (medium *Medium) Close() error { result := C.GoVboxMediumClose(medium.cmedium) if C.GoVboxFAILED(result) != 0 { return errors.New(fmt.Sprintf("Failed to close IMedium: %x", result)) } return nil }
// WaitForCompletion waits for all the operations tracked by this to complete. // The timeout argument is in milliseconds. -1 is used to wait indefinitely. // It returns any error encountered. func (progress *Progress) WaitForCompletion(timeout int) error { result := C.GoVboxProgressWaitForCompletion(progress.cprogress, C.int(timeout)) if C.GoVboxFAILED(result) != 0 { return errors.New(fmt.Sprintf("Failed to wait on IProgress: %x", result)) } return nil }
// LockMachine obtains a lock on a VM, so it can be modified or started. // It returns any error encountered. func (session *Session) LockMachine(machine Machine, lockType LockType) error { result := C.GoVboxLockMachine(machine.cmachine, session.csession, C.PRUint32(lockType)) if C.GoVboxFAILED(result) != 0 { return errors.New(fmt.Sprintf("Failed to lock IMachine: %x", result)) } return nil }
// SetVramSize changes the machine's emulated mouse type. // It returns a number and any error encountered. func (machine *Machine) SetVramSize(vram uint) error { result := C.GoVboxSetMachineVRAMSize(machine.cmachine, C.PRUint32(vram)) if C.GoVboxFAILED(result) != 0 { return errors.New( fmt.Sprintf("Failed to set IMachine VRAM size: %x", result)) } return nil }
// UnlockMachine releases the VM locked by this session. // It returns any error encountered. func (session *Session) UnlockMachine() error { result := C.GoVboxUnlockMachine(session.csession) if C.GoVboxFAILED(result) != 0 { return errors.New( fmt.Sprintf("Failed to unlock ISession machine: %x", result)) } return nil }
// SaveSettings saves a machine's modified settings. // A new machine must have its settings saved before it can be registered. // It returns a boolean and any error encountered. func (machine *Machine) SaveSettings() error { result := C.GoVboxMachineSaveSettings(machine.cmachine) if C.GoVboxFAILED(result) != 0 { return errors.New( fmt.Sprintf("Failed to save IMachine settings: %x", result)) } return nil }
// GetDisplay obtains the display of the VM controlled by this. // It returns a new Display instance and any error encountered. func (console *Console) GetDisplay() (Display, error) { var display Display result := C.GoVboxGetConsoleDisplay(console.cconsole, &display.cdisplay) if C.GoVboxFAILED(result) != 0 || display.cdisplay == nil { return display, errors.New( fmt.Sprintf("Failed to get IConsole display: %x", result)) } return display, nil }
// GetMachine obtains the VM associated with this set of VM controls. // It returns a new Machine instance and any error encountered. func (console *Console) GetMachine() (Machine, error) { var machine Machine result := C.GoVboxGetConsoleMachine(console.cconsole, &machine.cmachine) if C.GoVboxFAILED(result) != 0 || machine.cmachine == nil { return machine, errors.New( fmt.Sprintf("Failed to get IConsole machine: %x", result)) } return machine, nil }
// GetSize returns the actual size of the image backing the medium. // The returned size can be smaller than the logical size for dynamically grown // images. // It returns a byte quantity and any error encountered. func (medium *Medium) GetSize() (int64, error) { var csize C.PRInt64 result := C.GoVboxGetMediumSize(medium.cmedium, &csize) if C.GoVboxFAILED(result) != 0 { return 0, errors.New(fmt.Sprintf("Failed to get IMedium size: %x", result)) } return int64(csize), nil }
// GetLogoFadeIn returns true if the BIOS logo fades in during boot. // It returns a boolean and any error encountered. func (settings *BiosSettings) GetLogoFadeIn() (bool, error) { var clogoFadeIn C.PRBool result := C.GoVboxGetBiosSettingsLogoFadeIn(settings.csettings, &clogoFadeIn) if C.GoVboxFAILED(result) != 0 { return false, errors.New( fmt.Sprintf("Failed to get IBiosSettings logoFadeIn: %x", result)) } return clogoFadeIn != 0, nil }
// GetSettingsModified asks VirtualBox if this machine has unsaved settings. // It returns a boolean and any error encountered. func (machine *Machine) GetSettingsModified() (bool, error) { var cmodified C.PRBool result := C.GoVboxGetMachineSettingsModified(machine.cmachine, &cmodified) if C.GoVboxFAILED(result) != 0 { return false, errors.New( fmt.Sprintf("Failed to get IMachine modified flag: %x", result)) } return cmodified != 0, nil }
// GetKeyboard obtains the keyboard of the VM controlled by this. // It returns a new Keyboard instance and any error encountered. func (console *Console) GetKeyboard() (Keyboard, error) { var keyboard Keyboard result := C.GoVboxGetConsoleKeyboard(console.cconsole, &keyboard.ckeyboard) if C.GoVboxFAILED(result) != 0 || keyboard.ckeyboard == nil { return keyboard, errors.New( fmt.Sprintf("Failed to get IConsole keyboard: %x", result)) } return keyboard, nil }
// GetMouse obtains the mouse of the VM controlled by this. // It returns a new Mouse instance and any error encountered. func (console *Console) GetMouse() (Mouse, error) { var mouse Mouse result := C.GoVboxGetConsoleMouse(console.cconsole, &mouse.cmouse) if C.GoVboxFAILED(result) != 0 || mouse.cmouse == nil { return mouse, errors.New( fmt.Sprintf("Failed to get IConsole mouse: %x", result)) } return mouse, nil }
// SetBootMenuMode sets whether the BIOS logo fades out during boot. // It any error encountered. func (settings *BiosSettings) SetBootMenuMode(menuMode BootMenuMode) error { result := C.GoVboxSetBiosSettingsBootMenuMode(settings.csettings, C.PRUint32(menuMode)) if C.GoVboxFAILED(result) != 0 { return errors.New( fmt.Sprintf("Failed to set IBiosSettings boot menu mode: %x", result)) } return nil }
// DeleteStorage starts deleting the image backing a storage medium. // It returns a Progress and any error encountered. func (medium *Medium) DeleteStorage() (Progress, error) { var progress Progress result := C.GoVboxMediumDeleteStorage(medium.cmedium, &progress.cprogress) if C.GoVboxFAILED(result) != 0 || progress.cprogress == nil { return progress, errors.New( fmt.Sprintf("Failed to delete IMedium storage: %x", result)) } return progress, nil }
// PowerDown starts forcibly powering off the controlled VM. // It returns a Progress and any error encountered. func (console *Console) PowerDown() (Progress, error) { var progress Progress result := C.GoVboxConsolePowerDown(console.cconsole, &progress.cprogress) if C.GoVboxFAILED(result) != 0 || progress.cprogress == nil { return progress, errors.New( fmt.Sprintf("Failed to power down VM via IConsole: %x", result)) } return progress, nil }
// GetType obtains the session's type. // It returns the SessionType and any error encountered. func (session *Session) GetType() (SessionType, error) { var ctype C.PRUint32 result := C.GoVboxGetSessionType(session.csession, &ctype) if C.GoVboxFAILED(result) != 0 { return 0, errors.New( fmt.Sprintf("Failed to get ISession type: %x", result)) } return SessionType(ctype), nil }
// GetMaxGuestVRAM reads the maximum allowed amount of video RAM on a guest VM. // It returns a megabyte quantity and any error encountered. func (props *SystemProperties) GetMaxGuestVram() (uint, error) { var cmaxVram C.ULONG result := C.GoVboxGetSystemPropertiesMaxGuestVRAM(props.cprops, &cmaxVram) if C.GoVboxFAILED(result) != 0 { return 0, errors.New( fmt.Sprintf("Failed to get ISystemProperties max VRAM: %x", result)) } return uint(cmaxVram), nil }
// GetMachine obtains the VM associated with this session. // It returns a new Machine instance and any error encountered. func (session *Session) GetMachine() (Machine, error) { var machine Machine result := C.GoVboxGetSessionMachine(session.csession, &machine.cmachine) if C.GoVboxFAILED(result) != 0 || machine.cmachine == nil { return machine, errors.New( fmt.Sprintf("Failed to get ISession machine: %x", result)) } return machine, nil }
// GetConsole obtains the controls for the VM associated with this session. // The call fails unless the VM associated with this session has started. // It returns a new Console instance and any error encountered. func (session *Session) GetConsole() (Console, error) { var console Console result := C.GoVboxGetSessionConsole(session.csession, &console.cconsole) if C.GoVboxFAILED(result) != 0 || console.cconsole == nil { return console, errors.New( fmt.Sprintf("Failed to get ISession console: %x", result)) } return console, nil }
// GetMaxGuestCpuCount reads the maximum number of CPUs on a guest VM. // It returns a number and any error encountered. func (props *SystemProperties) GetMaxGuestCpuCount() (uint, error) { var cmaxCpus C.ULONG result := C.GoVboxGetSystemPropertiesMaxGuestCpuCount(props.cprops, &cmaxCpus) if C.GoVboxFAILED(result) != 0 { return 0, errors.New( fmt.Sprintf("Failed to get ISystemProperties max CPUs: %x", result)) } return uint(cmaxCpus), nil }
// Release frees up the associated VirtualBox data. // After the call, this instance is invalid, and using it will cause errors. // It returns any error encountered. func (medium *Medium) Release() error { if medium.cmedium != nil { result := C.GoVboxIMediumRelease(medium.cmedium) if C.GoVboxFAILED(result) != 0 { return errors.New(fmt.Sprintf("Failed to release IMedium: %x", result)) } medium.cmedium = nil } return nil }
// GetState returns the last known medium state. // It returns a MediumState enum instance and any error encountered. func (medium *Medium) GetState() (MediumState, error) { var cstate C.PRUint32 result := C.GoVboxGetMediumState(medium.cmedium, &cstate) if C.GoVboxFAILED(result) != 0 { return 0, errors.New( fmt.Sprintf("Failed to get IMedium state: %x", result)) } return MediumState(cstate), nil }
// Release frees up the associated VirtualBox data. // After the call, this instance is invalid, and using it will cause errors. // It returns any error encountered. func (session *Session) Release() error { if session.csession != nil { result := C.GoVboxISessionRelease(session.csession) if C.GoVboxFAILED(result) != 0 { return errors.New(fmt.Sprintf("Failed to release ISession: %x", result)) } session.csession = nil } return nil }