github.com/vmware/govmomi@v0.43.0/simulator/host_datastore_system.go (about) 1 /* 2 Copyright (c) 2017 VMware, Inc. All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package simulator 18 19 import ( 20 "os" 21 "path" 22 23 "github.com/vmware/govmomi/units" 24 "github.com/vmware/govmomi/vim25/methods" 25 "github.com/vmware/govmomi/vim25/mo" 26 "github.com/vmware/govmomi/vim25/soap" 27 "github.com/vmware/govmomi/vim25/types" 28 ) 29 30 type HostDatastoreSystem struct { 31 mo.HostDatastoreSystem 32 33 Host *mo.HostSystem 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.Self = e.Reference() 76 } else { 77 // put datastore to folder and generate reference 78 folderPutChild(ctx, folder, ds) 79 } 80 81 ds.Summary.Datastore = &ds.Self 82 ds.Summary.Name = ds.Name 83 ds.Summary.Url = info.Url 84 ds.Capability = types.DatastoreCapability{ 85 DirectoryHierarchySupported: true, 86 RawDiskMappingsSupported: false, 87 PerFileThinProvisioningSupported: true, 88 StorageIORMSupported: types.NewBool(true), 89 NativeSnapshotSupported: types.NewBool(false), 90 TopLevelDirectoryCreateSupported: types.NewBool(true), 91 SeSparseSupported: types.NewBool(true), 92 } 93 94 dss.Datastore = append(dss.Datastore, ds.Self) 95 dss.Host.Datastore = dss.Datastore 96 parent := hostParent(dss.Host) 97 ctx.Map.AddReference(ctx, parent, &parent.Datastore, ds.Self) 98 99 // NOTE: browser must be created after ds is appended to dss.Datastore 100 if !found { 101 browser := &HostDatastoreBrowser{} 102 browser.Datastore = dss.Datastore 103 ds.Browser = ctx.Map.Put(browser).Reference() 104 105 ds.Summary.Capacity = int64(units.TB * 10) 106 ds.Summary.FreeSpace = ds.Summary.Capacity 107 108 info.FreeSpace = ds.Summary.FreeSpace 109 info.MaxMemoryFileSize = ds.Summary.Capacity 110 info.MaxFileSize = ds.Summary.Capacity 111 } 112 113 return nil 114 } 115 116 func (dss *HostDatastoreSystem) CreateLocalDatastore(ctx *Context, c *types.CreateLocalDatastore) soap.HasFault { 117 r := &methods.CreateLocalDatastoreBody{} 118 119 ds := &Datastore{} 120 ds.Name = c.Name 121 122 ds.Info = &types.LocalDatastoreInfo{ 123 DatastoreInfo: types.DatastoreInfo{ 124 Name: c.Name, 125 Url: c.Path, 126 }, 127 Path: c.Path, 128 } 129 130 ds.Summary.Type = string(types.HostFileSystemVolumeFileSystemTypeOTHER) 131 ds.Summary.MaintenanceMode = string(types.DatastoreSummaryMaintenanceModeStateNormal) 132 ds.Summary.Accessible = true 133 134 if err := dss.add(ctx, ds); err != nil { 135 r.Fault_ = err 136 return r 137 } 138 139 ds.Host = append(ds.Host, types.DatastoreHostMount{ 140 Key: dss.Host.Reference(), 141 MountInfo: types.HostMountInfo{ 142 AccessMode: string(types.HostMountModeReadWrite), 143 Mounted: types.NewBool(true), 144 Accessible: types.NewBool(true), 145 }, 146 }) 147 148 _ = ds.RefreshDatastore(&types.RefreshDatastore{This: ds.Self}) 149 150 r.Res = &types.CreateLocalDatastoreResponse{ 151 Returnval: ds.Self, 152 } 153 154 return r 155 } 156 157 func (dss *HostDatastoreSystem) CreateNasDatastore(ctx *Context, c *types.CreateNasDatastore) soap.HasFault { 158 r := &methods.CreateNasDatastoreBody{} 159 160 // validate RemoteHost and RemotePath are specified 161 if c.Spec.RemoteHost == "" { 162 r.Fault_ = Fault( 163 "A specified parameter was not correct: Spec.RemoteHost", 164 &types.InvalidArgument{InvalidProperty: "RemoteHost"}, 165 ) 166 return r 167 } 168 if c.Spec.RemotePath == "" { 169 r.Fault_ = Fault( 170 "A specified parameter was not correct: Spec.RemotePath", 171 &types.InvalidArgument{InvalidProperty: "RemotePath"}, 172 ) 173 return r 174 } 175 176 ds := &Datastore{} 177 ds.Name = path.Base(c.Spec.LocalPath) 178 179 ds.Info = &types.NasDatastoreInfo{ 180 DatastoreInfo: types.DatastoreInfo{ 181 Url: c.Spec.LocalPath, 182 }, 183 Nas: &types.HostNasVolume{ 184 HostFileSystemVolume: types.HostFileSystemVolume{ 185 Name: c.Spec.LocalPath, 186 Type: c.Spec.Type, 187 }, 188 RemoteHost: c.Spec.RemoteHost, 189 RemotePath: c.Spec.RemotePath, 190 }, 191 } 192 193 ds.Summary.Type = c.Spec.Type 194 ds.Summary.MaintenanceMode = string(types.DatastoreSummaryMaintenanceModeStateNormal) 195 ds.Summary.Accessible = true 196 197 if err := dss.add(ctx, ds); err != nil { 198 r.Fault_ = err 199 return r 200 } 201 202 _ = ds.RefreshDatastore(&types.RefreshDatastore{This: ds.Self}) 203 204 r.Res = &types.CreateNasDatastoreResponse{ 205 Returnval: ds.Self, 206 } 207 208 return r 209 }