Skip to content
Closed
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"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you recall why you commented this out?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup agree with your comment above for loglevel. This is necessary due to an error that was being returned. It was throwing a returnval error which seemed aligned to not parsing the information correctly.


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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain this? It seems unused.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remnant of troubleshooting.


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