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 }