github.com/vmware/govmomi@v0.51.0/simulator/host_datastore_system.go (about)

     1  // © Broadcom. All Rights Reserved.
     2  // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package simulator
     6  
     7  import (
     8  	"fmt"
     9  	"os"
    10  	"path"
    11  
    12  	"github.com/google/uuid"
    13  
    14  	"github.com/vmware/govmomi/vim25/methods"
    15  	"github.com/vmware/govmomi/vim25/mo"
    16  	"github.com/vmware/govmomi/vim25/soap"
    17  	"github.com/vmware/govmomi/vim25/types"
    18  )
    19  
    20  type HostDatastoreSystem struct {
    21  	mo.HostDatastoreSystem
    22  
    23  	Host *mo.HostSystem
    24  }
    25  
    26  var defaultDatastoreCapability = types.DatastoreCapability{
    27  	DirectoryHierarchySupported:      true,
    28  	RawDiskMappingsSupported:         false,
    29  	PerFileThinProvisioningSupported: true,
    30  	StorageIORMSupported:             types.NewBool(false),
    31  	NativeSnapshotSupported:          types.NewBool(false),
    32  	SeSparseSupported:                types.NewBool(false),
    33  	TopLevelDirectoryCreateSupported: types.NewBool(true),
    34  }
    35  
    36  func (dss *HostDatastoreSystem) add(ctx *Context, ds *Datastore) *soap.Fault {
    37  	info := ds.Info.GetDatastoreInfo()
    38  
    39  	info.Name = ds.Name
    40  
    41  	if e := ctx.Map.FindByName(ds.Name, dss.Datastore); e != nil {
    42  		return Fault(e.Reference().Value, &types.DuplicateName{
    43  			Name:   ds.Name,
    44  			Object: e.Reference(),
    45  		})
    46  	}
    47  
    48  	fi, err := os.Stat(info.Url)
    49  	if err == nil && !fi.IsDir() {
    50  		err = os.ErrInvalid
    51  	}
    52  
    53  	if err != nil {
    54  		switch {
    55  		case os.IsNotExist(err):
    56  			return Fault(err.Error(), &types.NotFound{})
    57  		default:
    58  			return Fault(err.Error(), &types.HostConfigFault{})
    59  		}
    60  	}
    61  
    62  	folder := ctx.Map.getEntityFolder(dss.Host, "datastore")
    63  
    64  	found := false
    65  	if e := ctx.Map.FindByName(ds.Name, folder.ChildEntity); e != nil {
    66  		if e.Reference().Type != "Datastore" {
    67  			return Fault(e.Reference().Value, &types.DuplicateName{
    68  				Name:   ds.Name,
    69  				Object: e.Reference(),
    70  			})
    71  		}
    72  
    73  		// if datastore already exists, use current reference
    74  		found = true
    75  		ds = e.(*Datastore)
    76  	} else {
    77  		ds.Summary.Datastore = &ds.Self
    78  		ds.Summary.Name = ds.Name
    79  		ds.Summary.Url = info.Url
    80  
    81  		// put datastore to folder and generate reference
    82  		folderPutChild(ctx, folder, ds)
    83  	}
    84  
    85  	ds.Host = append(ds.Host, types.DatastoreHostMount{
    86  		Key: dss.Host.Reference(),
    87  		MountInfo: types.HostMountInfo{
    88  			AccessMode: string(types.HostMountModeReadWrite),
    89  			Mounted:    types.NewBool(true),
    90  			Accessible: types.NewBool(true),
    91  		},
    92  	})
    93  
    94  	_ = ds.RefreshDatastore(ctx, &types.RefreshDatastore{This: ds.Self})
    95  
    96  	dss.Datastore = append(dss.Datastore, ds.Self)
    97  	dss.Host.Datastore = dss.Datastore
    98  	parent := hostParent(ctx, dss.Host)
    99  	ctx.Map.AddReference(ctx, parent, &parent.Datastore, ds.Self)
   100  
   101  	// NOTE: browser must be created after ds is appended to dss.Datastore
   102  	if !found {
   103  		browser := &HostDatastoreBrowser{}
   104  		browser.Datastore = dss.Datastore
   105  		ds.Browser = ctx.Map.Put(browser).Reference()
   106  	}
   107  
   108  	return nil
   109  }
   110  
   111  func (dss *HostDatastoreSystem) CreateLocalDatastore(ctx *Context, c *types.CreateLocalDatastore) soap.HasFault {
   112  	r := &methods.CreateLocalDatastoreBody{}
   113  
   114  	ds := &Datastore{}
   115  	ds.Name = c.Name
   116  
   117  	ds.Info = &types.LocalDatastoreInfo{
   118  		DatastoreInfo: types.DatastoreInfo{
   119  			Name: c.Name,
   120  			Url:  c.Path,
   121  		},
   122  		Path: c.Path,
   123  	}
   124  
   125  	ds.Summary.Type = string(types.HostFileSystemVolumeFileSystemTypeOTHER)
   126  	ds.Summary.MaintenanceMode = string(types.DatastoreSummaryMaintenanceModeStateNormal)
   127  	ds.Summary.Accessible = true
   128  	ds.Capability = defaultDatastoreCapability
   129  
   130  	if err := dss.add(ctx, ds); err != nil {
   131  		r.Fault_ = err
   132  		return r
   133  	}
   134  
   135  	r.Res = &types.CreateLocalDatastoreResponse{
   136  		Returnval: ds.Self,
   137  	}
   138  
   139  	return r
   140  }
   141  
   142  func (dss *HostDatastoreSystem) CreateNasDatastore(ctx *Context, c *types.CreateNasDatastore) soap.HasFault {
   143  	r := &methods.CreateNasDatastoreBody{}
   144  
   145  	// validate RemoteHost and RemotePath are specified
   146  	if c.Spec.RemoteHost == "" {
   147  		r.Fault_ = Fault(
   148  			"A specified parameter was not correct: Spec.RemoteHost",
   149  			&types.InvalidArgument{InvalidProperty: "RemoteHost"},
   150  		)
   151  		return r
   152  	}
   153  	if c.Spec.RemotePath == "" {
   154  		r.Fault_ = Fault(
   155  			"A specified parameter was not correct: Spec.RemotePath",
   156  			&types.InvalidArgument{InvalidProperty: "RemotePath"},
   157  		)
   158  		return r
   159  	}
   160  
   161  	ds := &Datastore{}
   162  	ds.Name = path.Base(c.Spec.LocalPath)
   163  
   164  	ds.Info = &types.NasDatastoreInfo{
   165  		DatastoreInfo: types.DatastoreInfo{
   166  			Url: c.Spec.LocalPath,
   167  		},
   168  		Nas: &types.HostNasVolume{
   169  			HostFileSystemVolume: types.HostFileSystemVolume{
   170  				Name: c.Spec.LocalPath,
   171  				Type: c.Spec.Type,
   172  			},
   173  			RemoteHost: c.Spec.RemoteHost,
   174  			RemotePath: c.Spec.RemotePath,
   175  		},
   176  	}
   177  
   178  	ds.Summary.Type = c.Spec.Type
   179  	ds.Summary.MaintenanceMode = string(types.DatastoreSummaryMaintenanceModeStateNormal)
   180  	ds.Summary.Accessible = true
   181  	ds.Capability = defaultDatastoreCapability
   182  
   183  	if err := dss.add(ctx, ds); err != nil {
   184  		r.Fault_ = err
   185  		return r
   186  	}
   187  
   188  	r.Res = &types.CreateNasDatastoreResponse{
   189  		Returnval: ds.Self,
   190  	}
   191  
   192  	return r
   193  }
   194  
   195  func (dss *HostDatastoreSystem) createVsanDatastore(ctx *Context) types.BaseMethodFault {
   196  	ds := &Datastore{}
   197  	ds.Name = "vsanDatastore"
   198  
   199  	home := ctx.Map.OptionManager().find("vcsim.home").Value
   200  	dc := ctx.Map.getEntityDatacenter(dss.Host)
   201  	url := fmt.Sprintf("%s/%s-%s", home, dc.Name, ds.Name)
   202  	if err := os.MkdirAll(url, 0700); err != nil {
   203  		return ctx.Map.FileManager().fault(url, err, new(types.CannotAccessFile))
   204  	}
   205  
   206  	ds.Info = &types.VsanDatastoreInfo{
   207  		DatastoreInfo: types.DatastoreInfo{
   208  			Name: ds.Name,
   209  			Url:  url,
   210  		},
   211  		MembershipUuid: uuid.NewString(),
   212  	}
   213  
   214  	ds.Summary.Type = string(types.HostFileSystemVolumeFileSystemTypeVsan)
   215  	ds.Summary.MaintenanceMode = string(types.DatastoreSummaryMaintenanceModeStateNormal)
   216  	ds.Summary.Accessible = true
   217  	ds.Capability = defaultDatastoreCapability
   218  	ds.Capability.TopLevelDirectoryCreateSupported = types.NewBool(false)
   219  
   220  	if err := dss.add(ctx, ds); err != nil {
   221  		return err.Detail.Fault.(types.BaseMethodFault)
   222  	}
   223  
   224  	return nil
   225  }