Skip to content

Commit

Permalink
api: add object.Datastore.FindInventoryPath
Browse files Browse the repository at this point in the history
Helper to set Datastore InventoryPath and DatacenterPath,
needed by NewURL() to compose an upload/download endpoint URL

Fixes vmware#3267
  • Loading branch information
dougm committed Nov 3, 2023
1 parent 35b0fff commit 31423b7
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 7 deletions.
34 changes: 29 additions & 5 deletions object/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,31 @@ func NewDatastore(c *vim25.Client, ref types.ManagedObjectReference) *Datastore
}
}

// FindInventoryPath sets InventoryPath and DatacenterPath,
// needed by NewURL() to compose an upload/download endpoint URL
func (d *Datastore) FindInventoryPath(ctx context.Context) error {
entities, err := mo.Ancestors(ctx, d.c, d.c.ServiceContent.PropertyCollector, d.r)
if err != nil {
return err
}

val := "/"

for _, entity := range entities {
if entity.Parent == nil {
continue // root folder
}
val = path.Join(val, entity.Name)
if entity.Self.Type == "Datacenter" {
d.DatacenterPath = val
}
}

d.InventoryPath = val

return nil
}

func (d Datastore) Path(path string) string {
var p DatastorePath
if p.FromString(path) {
Expand Down Expand Up @@ -101,11 +126,6 @@ func (d Datastore) NewURL(path string) *url.URL {
}
}

// URL is deprecated, use NewURL instead.
func (d Datastore) URL(ctx context.Context, dc *Datacenter, path string) (*url.URL, error) {
return d.NewURL(path), nil
}

func (d Datastore) Browser(ctx context.Context) (*HostDatastoreBrowser, error) {
var do mo.Datastore

Expand Down Expand Up @@ -186,6 +206,10 @@ func (d Datastore) HostContext(ctx context.Context, host *HostSystem) context.Co
// that can be used along with the ticket cookie to access the given path. An host is chosen at random unless the
// the given Context was created with a specific host via the HostContext method.
func (d Datastore) ServiceTicket(ctx context.Context, path string, method string) (*url.URL, *http.Cookie, error) {
if d.InventoryPath == "" {
_ = d.FindInventoryPath(ctx)
}

u := d.NewURL(path)

host, ok := ctx.Value(datastoreServiceTicketHostKey{}).(*HostSystem)
Expand Down
82 changes: 80 additions & 2 deletions object/datastore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,85 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package object
package object_test

import (
"context"
"strings"
"testing"

"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/simulator"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/soap"
)

// Datastore should implement the Reference interface.
var _ Reference = Datastore{}
var _ object.Reference = object.Datastore{}

func TestDatastoreFindInventoryPath(t *testing.T) {
model := simulator.VPX()
model.Datacenter = 2
model.Datastore = 2

simulator.Test(func(ctx context.Context, c *vim25.Client) {
refs := simulator.Map.All("Datastore")

for _, obj := range refs {
ds := object.NewDatastore(c, obj.Reference())

upload := func() error {
p := soap.DefaultUpload
r := strings.NewReader(ds.Name())
p.ContentLength = r.Size()
return ds.Upload(ctx, r, "name.txt", &p)

}

// with InventoryPath not set
if err := upload(); err != nil {
t.Error(err)
}

if ds.InventoryPath != "" {
t.Error("InventoryPath should still be empty")
}

// Set InventoryPath and DatacenterPath
err := ds.FindInventoryPath(ctx)
if err != nil {
t.Fatal(err)
}

if !strings.HasPrefix(ds.InventoryPath, ds.DatacenterPath) {
t.Errorf("InventoryPath=%s, DatacenterPath=%s", ds.InventoryPath, ds.DatacenterPath)
}

// with InventoryPath set
if err := upload(); err != nil {
t.Error(err)
}

tests := []struct {
path, kind string
}{
{ds.InventoryPath, "Datastore"},
{ds.DatacenterPath, "Datacenter"},
}

for _, test := range tests {
ref, err := object.NewSearchIndex(c).FindByInventoryPath(ctx, test.path)
if err != nil {
t.Fatal(err)
}

if ref == nil {
t.Fatalf("failed to find %s", test.path)
}
if ref.Reference().Type != test.kind {
t.Errorf("%s is not a %s", test.path, test.kind)
}
}
}
}, model)
}

0 comments on commit 31423b7

Please sign in to comment.