Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions vboxwebsrv/vboxwebsrv.go
Original file line number Diff line number Diff line change
Expand Up @@ -15800,7 +15800,7 @@ type IAdditionsFacility struct {
}

type IMediumAttachment struct {
XMLName xml.Name `xml:"http://www.virtualbox.org/ IMediumAttachment"`
// XMLName xml.Name `xml:"http://www.virtualbox.org/ IMediumAttachment"`

Medium string `xml:"medium,omitempty"`
Controller string `xml:"controller,omitempty"`
Expand Down Expand Up @@ -20347,6 +20347,8 @@ func (service *VboxPortType) IMachinegetMedium(request *IMachinegetMedium) (*IMa
// - InvalidObjectFault
// - RuntimeFault

type Returnval *IMediumAttachment

func (service *VboxPortType) IMachinegetMediumAttachmentsOfController(request *IMachinegetMediumAttachmentsOfController) (*IMachinegetMediumAttachmentsOfControllerResponse, error) {
response := new(IMachinegetMediumAttachmentsOfControllerResponse)
err := service.client.Call("", request, response)
Expand Down Expand Up @@ -33330,17 +33332,20 @@ func (s *SOAPClient) Call(soapAction string, request, response interface{}) erro
encoder := xml.NewEncoder(buffer)
//encoder.Indent(" ", " ")

err := encoder.Encode(envelope)
if err == nil {
err = encoder.Flush()
if err := encoder.Encode(envelope); err != nil {
return err
}

log.Println(buffer.String())
if err != nil {
if err := encoder.Flush(); err != nil {
return err
}

// log.Println(buffer.String())

req, err := http.NewRequest("POST", s.url, buffer)
if err != nil {
return err
}
if s.auth != nil {
req.SetBasicAuth(s.auth.Login, s.auth.Password)
}
Expand Down Expand Up @@ -33368,12 +33373,16 @@ func (s *SOAPClient) Call(soapAction string, request, response interface{}) erro
defer res.Body.Close()

rawbody, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}

if len(rawbody) == 0 {
log.Println("empty response")
return nil
}

log.Println(string(rawbody))
// log.Println(string(rawbody))
respEnvelope := new(SOAPEnvelope)
respEnvelope.Body = SOAPBody{Content: response}
err = xml.Unmarshal(rawbody, respEnvelope)
Expand Down
49 changes: 49 additions & 0 deletions virtualboxclient/hard_disk.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package virtualboxclient

type HardDisk struct {
virtualbox *VirtualBox
managedObjectId string
}

type HardDisks struct {
disks []*HardDisk
}

func (h *HardDisk) getMedium() *Medium {
return &Medium{virtualbox: h.virtualbox, managedObjectId: h.managedObjectId}
}

func isSet(value string) bool {
return value != ""
}

func (hs *HardDisks) GetMedium(objectID, name string) ([]*Medium, error) {
var ms []*Medium
for _, hardDisk := range hs.disks {
om := hardDisk.getMedium()
var m *Medium
if isSet(name) || isSet(objectID) {
var err error
m, err = om.GetIDName()
if err != nil {
return nil, err
}
}

if isSet(name) && m.Name != name {
continue
}

if isSet(objectID) && m.ID != objectID {
continue
}

medium, err := om.Get()
if err != nil {
return nil, err
}
ms = append(ms, medium)
}

return ms, nil
}
242 changes: 241 additions & 1 deletion virtualboxclient/machine.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package virtualboxclient

import (
"errors"

"github.com/appropriate/go-virtualboxclient/vboxwebsrv"
)

type Machine struct {
virtualbox *VirtualBox
managedObjectId string
ID string
Name string
}

func (m *Machine) GetChipsetType() (*vboxwebsrv.ChipsetType, error) {
Expand All @@ -28,6 +32,18 @@ func (m *Machine) GetMediumAttachments() ([]*vboxwebsrv.IMediumAttachment, error
return nil, err // TODO: Wrap the error
}

ret := response.Returnval
return ret, nil
}

func (m *Machine) GetMediumAttachmentsOfController(cName string) ([]*vboxwebsrv.IMediumAttachment, error) {
request := vboxwebsrv.IMachinegetMediumAttachmentsOfController{This: m.managedObjectId, Name: cName}

response, err := m.virtualbox.IMachinegetMediumAttachmentsOfController(&request)
if err != nil {
return nil, err // TODO: Wrap the error
}

return response.Returnval, nil
}

Expand All @@ -53,6 +69,29 @@ func (m *Machine) GetSettingsFilePath() (string, error) {
return response.Returnval, nil
}

func (m *Machine) SaveSettings() error {
request := vboxwebsrv.IMachinesaveSettings{This: m.managedObjectId}

_, err := m.virtualbox.IMachinesaveSettings(&request)
if err != nil {
defer m.DiscardSettings()
return err // TODO: Wrap the error
}

return nil
}

func (m *Machine) DiscardSettings() error {
request := vboxwebsrv.IMachinediscardSettings{This: m.managedObjectId}

_, err := m.virtualbox.IMachinediscardSettings(&request)
if err != nil {
return err // TODO: Wrap the error
}

return nil
}

func (m *Machine) GetStorageControllers() ([]*StorageController, error) {
request := vboxwebsrv.IMachinegetStorageControllers{This: m.managedObjectId}

Expand All @@ -63,8 +102,209 @@ func (m *Machine) GetStorageControllers() ([]*StorageController, error) {

storageControllers := make([]*StorageController, len(response.Returnval))
for i, oid := range response.Returnval {
storageControllers[i] = &StorageController{m.virtualbox, oid}
storageControllers[i] = &StorageController{virtualbox: m.virtualbox, managedObjectId: oid}
}

return storageControllers, nil
}

func (m *Machine) GetStorageController(name string) (*StorageController, error) {
if name == "" {
return nil, errors.New("storage controller name not specified")
}
scs, err := m.GetStorageControllers()
if err != nil {
return nil, err
}

for _, sc := range scs {
scName, err := sc.GetName()
if err != nil {
return nil, err
}
if scName == name {
sc.Name = scName
return sc, nil
}
}
return nil, errors.New("storage controller not found")
}

func (m *Machine) AttachDevice(medium *Medium) error {
session, err := m.virtualbox.GetSession()
if err != nil {
return err
}
// defer session.Release()

if err := m.Lock(session, vboxwebsrv.LockTypeShared); err != nil {
return err
}
defer m.Unlock(session)

sm, err := session.GetMachine()
if err != nil {
return err
}
defer sm.Release()

if m.virtualbox.controllerName == "" {
return errors.New("missing controllerName")
}

sc, err := sm.GetStorageController(m.virtualbox.controllerName)
if err != nil {
return err
}

pn, err := sc.GetNextAvailablePort(m)
if err != nil {
return err
}

pc, err := sc.GetPortCount()
if err != nil {
return err
}

spc := uint32(pn) + 1
if spc > pc {
if err := sc.SetPortCount(spc); err != nil {
return err
}
}

request := vboxwebsrv.IMachineattachDevice{
This: sm.managedObjectId,
Name: sc.Name,
ControllerPort: pn,
Device: 0,
Type_: &medium.DeviceType,
Medium: medium.managedObjectId,
}

_, err = m.virtualbox.IMachineattachDevice(&request)
if err != nil {
return err
}

if err := sm.SaveSettings(); err != nil {
return err
}

if err := m.Unlock(session); err != nil {
return err
}

return nil
}

func (m *Machine) DetachDevice(medium *Medium) error {

session, err := m.virtualbox.GetSession()
if err != nil {
return err
}
// defer session.Release()

if err := m.Lock(session, vboxwebsrv.LockTypeShared); err != nil {
return err
}
defer m.Unlock(session)

sm, err := session.GetMachine()
if err != nil {
return err
}
defer sm.Release()

mediumAttachments, err := m.GetMediumAttachments()
if err != nil {
return err
}

var request *vboxwebsrv.IMachinedetachDevice
for _, ma := range mediumAttachments {
am := &Medium{virtualbox: m.virtualbox, managedObjectId: ma.Medium}
defer am.Release()
amID, err := am.GetID()
if err != nil {
return err
}

if amID != medium.ID {
continue
}
request = &vboxwebsrv.IMachinedetachDevice{
This: sm.managedObjectId,
Name: ma.Controller,
ControllerPort: ma.Port,
Device: 0,
}
}
if request == nil {
return errors.New("couldn't find attached medium")
}

_, err = m.virtualbox.IMachinedetachDevice(request)
if err != nil {
return err
}

if err := sm.SaveSettings(); err != nil {
return err
}

return nil
}

func (m *Machine) Unlock(session *Session) error {
if err := session.UnlockMachine(); err != nil {
return err
}
return nil
}

func (m *Machine) Lock(session *Session, lockType vboxwebsrv.LockType) error {
if err := session.LockMachine(m, lockType); err != nil {
return err
}
return nil
}

func (m *Machine) GetID() (string, error) {
request := vboxwebsrv.IMachinegetId{This: m.managedObjectId}

response, err := m.virtualbox.IMachinegetId(&request)
if err != nil {
return "", err // TODO: Wrap the error
}

// TODO: See if we need to do anything with the response
return response.Returnval, nil
}

func (m *Machine) GetName() (string, error) {
request := vboxwebsrv.IMachinegetName{This: m.managedObjectId}

response, err := m.virtualbox.IMachinegetName(&request)
if err != nil {
return "", err // TODO: Wrap the error
}

// TODO: See if we need to do anything with the response
return response.Returnval, nil
}

func (m *Machine) Release() error {
return m.virtualbox.Release(m.managedObjectId)
}

func (m *Machine) Refresh() error {
if mr, err := m.virtualbox.FindMachine(m.ID); err != nil {
return err
} else {
m.managedObjectId = mr.managedObjectId
}
return nil
}
Loading