Skip to content

Commit 22c7be3

Browse files
committed
vcsim: Use vmdk.Descriptor for vmdk file metadata
A vcsim VirtualDisk had consisted of two empty files: ${name}.vmdk and ${name}-flat.vmdk Adding the vmdk.Descriptor to ${name}.vmdk as real VC does, allows methods to determine the vmdk capacity independent of a VirtualDevice. Needed to fix a few bugs in the process related to VM storage accounting and nfc GET. Signed-off-by: Doug MacEachern <[email protected]>
1 parent eaaeb84 commit 22c7be3

File tree

8 files changed

+162
-137
lines changed

8 files changed

+162
-137
lines changed

simulator/file_manager.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/vmware/govmomi/vim25/mo"
1515
"github.com/vmware/govmomi/vim25/soap"
1616
"github.com/vmware/govmomi/vim25/types"
17+
"github.com/vmware/govmomi/vmdk"
1718
)
1819

1920
type FileManager struct {
@@ -111,6 +112,45 @@ func (f *FileManager) deleteDatastoreFile(ctx *Context, req *types.DeleteDatasto
111112
return nil
112113
}
113114

115+
func (f *FileManager) DiskDescriptor(ctx *Context, dc *types.ManagedObjectReference, name string) (*vmdk.Descriptor, string, types.BaseMethodFault) {
116+
path, fault := f.resolve(ctx, dc, name)
117+
if fault != nil {
118+
return nil, "", fault
119+
}
120+
121+
file, err := os.Open(path)
122+
if err != nil {
123+
return nil, "", f.fault(name, err, new(types.FileFault))
124+
}
125+
126+
defer file.Close()
127+
128+
desc, err := vmdk.ParseDescriptor(file)
129+
if err != nil {
130+
return nil, "", f.fault(name, err, new(types.FileFault))
131+
}
132+
133+
return desc, path, nil
134+
}
135+
136+
func (f *FileManager) SaveDiskDescriptor(ctx *Context, desc *vmdk.Descriptor, path string) types.BaseMethodFault {
137+
file, err := os.Create(path)
138+
if err != nil {
139+
return f.fault(path, err, new(types.FileFault))
140+
}
141+
142+
if err = desc.Write(file); err != nil {
143+
_ = file.Close()
144+
return f.fault(path, err, new(types.FileFault))
145+
}
146+
147+
if err = file.Close(); err != nil {
148+
return f.fault(path, err, new(types.FileFault))
149+
}
150+
151+
return nil
152+
}
153+
114154
func (f *FileManager) DeleteDatastoreFileTask(ctx *Context, req *types.DeleteDatastoreFile_Task) soap.HasFault {
115155
task := CreateTask(f, "deleteDatastoreFile", func(*Task) (types.AnyType, types.BaseMethodFault) {
116156
return nil, f.deleteDatastoreFile(ctx, req)

simulator/http_nfc_lease.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,14 @@ func ServeNFC(w http.ResponseWriter, r *http.Request) {
5959
}
6060

6161
status := http.StatusOK
62-
var dst hash.Hash
62+
var sum hash.Hash
63+
var dst io.Writer = w
6364
var src io.ReadCloser
6465

6566
switch r.Method {
6667
case http.MethodPut, http.MethodPost:
67-
dst = sha1.New()
68+
sum = sha1.New()
69+
dst = sum
6870
src = r.Body
6971
case http.MethodGet:
7072
f, err := os.Open(file)
@@ -79,9 +81,9 @@ func ServeNFC(w http.ResponseWriter, r *http.Request) {
7981

8082
n, err := io.Copy(dst, src)
8183
_ = src.Close()
82-
if dst != nil {
84+
if sum != nil {
8385
lease.metadata[name] = metadata{
84-
sha1: dst.Sum(nil),
86+
sha1: sum.Sum(nil),
8587
size: n,
8688
}
8789
}

simulator/virtual_disk_manager.go

Lines changed: 48 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,18 @@
55
package simulator
66

77
import (
8+
"errors"
89
"fmt"
910
"os"
10-
"strconv"
11+
"path/filepath"
1112
"strings"
1213

1314
"github.com/vmware/govmomi/internal"
1415
"github.com/vmware/govmomi/vim25/methods"
1516
"github.com/vmware/govmomi/vim25/mo"
1617
"github.com/vmware/govmomi/vim25/soap"
1718
"github.com/vmware/govmomi/vim25/types"
19+
"github.com/vmware/govmomi/vmdk"
1820
)
1921

2022
type VirtualDiskManager struct {
@@ -46,79 +48,72 @@ func vdmCreateVirtualDisk(ctx *Context, op types.VirtualDeviceConfigSpecFileOper
4648

4749
shouldReplace := op == types.VirtualDeviceConfigSpecFileOperationReplace
4850
shouldExist := op == ""
49-
for _, name := range vdmNames(file) {
50-
_, err := os.Stat(name)
51-
if err == nil {
52-
if shouldExist {
53-
return nil
54-
}
55-
if shouldReplace {
56-
if err = os.Truncate(file, 0); err != nil {
57-
return fm.fault(name, err, new(types.CannotCreateFile))
58-
}
59-
return nil
60-
}
61-
return fm.fault(name, nil, new(types.FileAlreadyExists))
62-
} else if shouldExist {
63-
return fm.fault(name, nil, new(types.FileNotFound))
64-
}
6551

66-
f, err := os.Create(name)
67-
if err != nil {
68-
return fm.fault(name, err, new(types.CannotCreateFile))
52+
_, err := os.Stat(file)
53+
if err == nil {
54+
if shouldExist {
55+
return nil
56+
}
57+
if !shouldReplace {
58+
return fm.fault(file, nil, new(types.FileAlreadyExists))
6959
}
60+
} else if shouldExist {
61+
return fm.fault(file, nil, new(types.FileNotFound))
62+
}
7063

71-
if req.Spec != nil {
72-
var spec any = req.Spec
73-
fileBackedSpec, ok := spec.(*types.FileBackedVirtualDiskSpec)
64+
backing := VirtualDiskBackingFileName(file)
7465

75-
if !ok {
76-
return fm.fault(name, nil, new(types.FileFault))
77-
}
66+
extent := vmdk.Extent{
67+
Info: filepath.Base(backing),
68+
}
7869

79-
if _, err = f.WriteString(strconv.FormatInt(fileBackedSpec.CapacityKb, 10)); err != nil {
80-
return fm.fault(name, err, new(types.FileFault))
81-
}
70+
f, err := os.Create(file)
71+
if err != nil {
72+
return fm.fault(file, err, new(types.CannotCreateFile))
73+
}
74+
75+
defer f.Close()
76+
77+
if req.Spec != nil {
78+
spec, ok := req.Spec.(types.BaseFileBackedVirtualDiskSpec)
79+
if !ok {
80+
return fm.fault(file, nil, new(types.FileFault))
8281
}
8382

84-
_ = f.Close()
83+
fileSpec := spec.GetFileBackedVirtualDiskSpec()
84+
extent.Size = fileSpec.CapacityKb * 1024 / vmdk.SectorSize
85+
}
86+
87+
desc := vmdk.NewDescriptor(extent)
88+
if err := desc.Write(f); err != nil {
89+
return fm.fault(file, err, new(types.FileFault))
8590
}
8691

92+
b, err := os.Create(backing)
93+
if err != nil {
94+
return fm.fault(backing, err, new(types.CannotCreateFile))
95+
}
96+
_ = b.Close()
97+
8798
return nil
8899
}
89100

90101
func vdmExtendVirtualDisk(ctx *Context, req *types.ExtendVirtualDisk_Task) types.BaseMethodFault {
91102
fm := ctx.Map.FileManager()
92103

93-
file, fault := fm.resolve(ctx, req.Datacenter, req.Name)
104+
desc, file, fault := fm.DiskDescriptor(ctx, req.Datacenter, req.Name)
94105
if fault != nil {
95106
return fault
96107
}
97108

98-
for _, name := range vdmNames(file) {
99-
_, err := os.Stat(name)
100-
if err == nil {
101-
content, err := os.ReadFile(name)
102-
if err != nil {
103-
return fm.fault(name, err, new(types.FileFault))
104-
}
105-
106-
capacity, err := strconv.Atoi(string(content))
107-
if err != nil {
108-
return fm.fault(name, err, new(types.FileFault))
109-
}
110-
111-
if int64(capacity) > req.NewCapacityKb {
112-
// cannot shrink disk
113-
return fm.fault(name, nil, new(types.FileFault))
114-
}
115-
return nil
116-
} else {
117-
return fm.fault(name, nil, new(types.FileNotFound))
118-
}
109+
newCapacity := req.NewCapacityKb * 1024
110+
if desc.Capacity() > newCapacity {
111+
return fm.fault(req.Name, errors.New("cannot shrink disk"), new(types.FileFault))
119112
}
120113

121-
return nil
114+
desc.Extent[0].Size = newCapacity / vmdk.SectorSize
115+
116+
return fm.SaveDiskDescriptor(ctx, desc, file)
122117
}
123118

124119
func (m *VirtualDiskManager) CreateVirtualDiskTask(ctx *Context, req *types.CreateVirtualDisk_Task) soap.HasFault {

0 commit comments

Comments
 (0)