diff --git a/pkg/hostman/storageman/imagecachemanager_agent.go b/pkg/hostman/storageman/imagecachemanager_agent.go index 51c9d34376..a05a09c66a 100644 --- a/pkg/hostman/storageman/imagecachemanager_agent.go +++ b/pkg/hostman/storageman/imagecachemanager_agent.go @@ -153,7 +153,7 @@ func (c *SAgentImageCacheManager) prefetchImageCacheByUpload(ctx context.Context return nil, err } localImgPath, _ := localImage.GetString("path") - localImgSize, _ := localImage.Int("size") + //localImgSize, _ := localImage.Int("size") client, err := esxi.NewESXiClientFromAccessInfo(ctx, &data.Datastore) if err != nil { @@ -183,14 +183,13 @@ func (c *SAgentImageCacheManager) prefetchImageCacheByUpload(ctx context.Context exists = true } } else { - ret, err := ds.CheckFile(ctx, remotePath) + _, err := ds.ListPath(ctx, remotePath) if err != nil { - log.Debugf("ds.CheckFile failed: %s", err) - } else { - if int64(ret.Size) == localImgSize { - // exist and same size - exists = true + if errors.Cause(err) != errors.ErrNotFound { + return nil, errors.Wrapf(err, "unable to check file with path %s", remotePath) } + } else { + exists = true } } log.Debugf("exist: %t, remotePath: %s", exists, remotePath) diff --git a/pkg/multicloud/esxi/storage.go b/pkg/multicloud/esxi/storage.go index 1aab08ff69..6524c0a6b4 100644 --- a/pkg/multicloud/esxi/storage.go +++ b/pkg/multicloud/esxi/storage.go @@ -593,6 +593,91 @@ func (self *SDatastore) ListDir(ctx context.Context, remotePath string) ([]SData return ret, nil } +func (self *SDatastore) listPath(b *object.HostDatastoreBrowser, path string, spec types.HostDatastoreBrowserSearchSpec) ([]types.HostDatastoreBrowserSearchResults, error) { + ctx := context.TODO() + + path = self.getDatastoreObj().Path(path) + + search := b.SearchDatastore + + task, err := search(ctx, path, &spec) + if err != nil { + return nil, err + } + + info, err := task.WaitForResult(ctx, nil) + if err != nil { + return nil, err + } + + switch r := info.Result.(type) { + case types.HostDatastoreBrowserSearchResults: + return []types.HostDatastoreBrowserSearchResults{r}, nil + case types.ArrayOfHostDatastoreBrowserSearchResults: + return r.HostDatastoreBrowserSearchResults, nil + default: + return nil, errors.Error(fmt.Sprintf("unknown result type: %T", r)) + } + +} + +func (self *SDatastore) ListPath(ctx context.Context, remotePath string) ([]types.HostDatastoreBrowserSearchResults, error) { + //types.HostDatastoreBrowserSearchResults + ds := self.getDatastoreObj() + + b, err := ds.Browser(ctx) + if err != nil { + return nil, err + } + + ret := make([]types.HostDatastoreBrowserSearchResults, 0) + + spec := types.HostDatastoreBrowserSearchSpec{ + MatchPattern: []string{"*"}, + Details: &types.FileQueryFlags{ + FileType: true, + FileSize: true, + FileOwner: types.NewBool(true), // TODO: omitempty is generated, but seems to be required + Modification: true, + }, + } + + for i := 0; ; i++ { + r, err := self.listPath(b, remotePath, spec) + if err != nil { + // Treat the argument as a match pattern if not found as directory + if i == 0 && types.IsFileNotFound(err) || isInvalid(err) { + spec.MatchPattern[0] = path.Base(remotePath) + remotePath = path.Dir(remotePath) + continue + } + if types.IsFileNotFound(err) { + return nil, errors.ErrNotFound + } + return nil, err + } + if i == 1 && len(r) == 1 && len(r[0].File) == 0 { + return nil, errors.ErrNotFound + } + for n := range r { + ret = append(ret, r[n]) + } + break + } + return ret, nil +} + +func isInvalid(err error) bool { + if f, ok := err.(types.HasFault); ok { + switch f.Fault().(type) { + case *types.InvalidArgument: + return true + } + } + + return false +} + func (self *SDatastore) CheckFile(ctx context.Context, remotePath string) (*SDatastoreFileInfo, error) { url := self.GetPathUrl(remotePath)